将org.apache.httpcomponents与App Engine一起使用时,无法调整套接字超时

时间:2014-04-16 07:47:22

标签: google-app-engine

我在本地开发服务器上测试了以下一段代码,其输入网址响应缓慢。

final HttpGet getMethod = getHttpGet(apiUrl);

RequestConfig config = RequestConfig.custom()
    .setSocketTimeout(60 * 1000)
    .setConnectTimeout(60 * 1000)
    .setConnectionRequestTimeout(60 * 1000)
    .build();
getMethod.setConfig(config);

httpClient = HttpClients.createDefault();
proxyResponse = httpClient.execute(getMethod);
if (proxyResponse.getStatusLine().getStatusCode() == HTTP_OK) {
    /* ... */
}

虽然套接字超时设置为60秒,但在6秒后我们看到org.apache.http.impl.execchain.RetryExec正在重试。在4次重试之后,请求失败并出现异常。看起来超时信息被忽略了。

INFO: Pre-render service making request:

Apr 15, 2014 4:49:01 PM com.github.greengerong.PreRenderSEOFilter dump
INFO:   GET http://api.ajaxsnapshots.com/makeSnapshot?url=http%3A%2F%2Fkarmademo.dyndns.dk%3A8080%2F HTTP/1.1
...
Apr 15, 2014 4:49:07 PM org.apache.http.impl.execchain.RetryExec execute
INFO: I/O exception (java.net.SocketException) caught when processing request: Socket operation timed out: The API call remote_socket.Receive() took too long to respond and was cancelled.
Apr 15, 2014 4:49:07 PM org.apache.http.impl.execchain.RetryExec execute
INFO: Retrying request
...
Apr 15, 2014 4:49:12 PM org.apache.http.impl.execchain.RetryExec execute
INFO: I/O exception (java.net.SocketException) caught when processing request: Socket operation timed out: The API call remote_socket.Receive() took too long to respond and was cancelled.
Apr 15, 2014 4:49:12 PM org.apache.http.impl.execchain.RetryExec execute
INFO: Retrying request
...
Apr 15, 2014 4:49:17 PM org.apache.http.impl.execchain.RetryExec execute
INFO: I/O exception (java.net.SocketException) caught when processing request: Socket operation timed out: The API call remote_socket.Receive() took too long to respond and was cancelled.
Apr 15, 2014 4:49:17 PM org.apache.http.impl.execchain.RetryExec execute
INFO: Retrying request
...
Apr 15, 2014 4:49:22 PM com.github.greengerong.PreRenderSEOFilter doFilter
WARNING: Prerender service error
java.net.SocketException: Socket operation timed out: The API call remote_socket.Receive() took too long to respond and was cancelled.
 at com.google.appengine.api.socket.SocketApiHelper.makeSyncCall(SocketApiHelper.java:73)
 at com.google.appengine.api.socket.AppEngineSocketImpl.receive(AppEngineSocketImpl.java:710)
 at com.google.appengine.api.socket.AppEngineSocketInputStream.read(AppEngineSocketInputStream.java:35)
 at org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SessionInputBufferImpl.java:136)
 at org.apache.http.impl.io.SessionInputBufferImpl.fillBuffer(SessionInputBufferImpl.java:152)
 at org.apache.http.impl.io.SessionInputBufferImpl.readLine(SessionInputBufferImpl.java:270)
 at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:140)
 at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:57)
 at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:260)
 at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:161)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:606)
 at com.google.appengine.tools.development.agent.runtime.Runtime.invoke(Runtime.java:115)
 at org.apache.http.impl.conn.CPoolProxy.invoke(CPoolProxy.java:138)
 at com.sun.proxy.$Proxy49.receiveResponseHeader(Unknown Source)
 at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:271)
 at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:123)
 at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:253)
 at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:194)
 at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:85)
 at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
 at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:186)
 at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
 at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
 at com.github.greengerong.PreRenderSEOFilter.proxyPrerenderedPageResponse(PreRenderSEOFilter.java:132)
 at com.github.greengerong.PreRenderSEOFilter.doFilter(PreRenderSEOFilter.java:84)

我切换到使用HttpURLConnection,我能够成功控制读取超时。

URL url = new URL(apiUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setReadTimeout(60 * 1000);

if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
    /* ... */
}

不确定为什么使用org.apache api我无法调整超时。只是想我发布以防万一有人知道,更重要的是,确保人们了解解决方法。

版本信息:

  • org.apache.httpcomponents - 4.3.1
  • app engine sdk - 1.9.0

0 个答案:

没有答案