這是本文件的舊版!


Connection Pool的Request Timeout沒有作用 (working..)

RestAPI的開發者,大都會非常頻繁的存取目標機器;Connection Pool是其中一個增進存取效率的方式。然而,這陣子在使用RESTEasy + Apache Connection Pool後,發現ConnectionRequestTimeout並沒作用。本篇文章主要分享目前的解決方法。

因為相依libraries的限制,我們目前還沒使用最新版本的RESTEasy,資訊如下:

resteasy-client: 3.0.14.Final
httpcore: 4.3.3
httpclient: 4.3.6

我寫了一個測試去確認ConnectionRequestTimeout是否有作用,方法如下:

  1. 將Pool大小設定為1。
  2. 設定ConnectionRequestTimeout為2秒。
  3. 依序發起兩個HTTP Get,但第一個請求不關閉。
  4. 接著發起第二個HTTP Get,由於沒有有效的連線可以使用,會Block。
  5. 在2秒後,Client會收到Exception,Root Cause為ConnectionPoolTimeoutException。

首先是HttpEngine設定的部分,由於這個版本ResteasyClientBuilder內建的PoolManager有些問題,因此我們是使用自己產生的,程式碼大致如下:

// 這使自己寫的Builder,產生的實體是PoolingHttpClientConnectionManager
private HttpClientConnectionManager initConnectionManager(int poolSize, int perRoute) {
	HttpClientConnectionManagerBuilder builder = new HttpClientConnectionManagerBuilder();
	return builder.withMaxTotal(poolSize).withDefaultMaxPerRoute(perRoute).build();
}
 
@Test(timeout=20000)
public void testRequestTimeoutWithCustomHttpEngine() throws Exception {
	int expectTimeout = 2*1000;
 
	connectionManager = initConnectionManager(20 , 1);
 
	RequestConfig requestConfig = RequestConfig.custom()
			.setConnectionRequestTimeout(expectTimeout)
			.build();
 
	ClientHttpEngine httpEngin = new ClientHttpEngineBuilder()
			.withRequestConfig(requestConfig)
			.withConnectionManager(connectionManager).build();
 
	ResteasyClientBuilder clientBuilder = (ResteasyClientBuilder)ResteasyClientBuilder.newBuilder();
	clientBuilder.httpEngine(httpEngin);
	// 以下略
}