On May 11, 2010, at 11:53am, Brooks, Kenneth S wrote:
In the 4.0.1 tutorial I see the following paragraph.
... begin snippet ...
HttpClient tries to mitigate the problem by testing whether the
connection is 'stale', that is no longer valid because it was closed
on the server side, prior to using the connection for executing an
HTTP request. The stale connection check is not 100% reliable and
adds 10 to 30 ms overhead to each request execution. The only
feasible solution that does not involve a one thread per socket
model for idle connections is a dedicated monitor thread used to
evict connections that are considered expired due to a long period
of inactivity. The monitor thread can periodically call
ClientConnectionManager#closeExpiredConnections() method to close
all expired connections and evict closed connections from the pool.
It can also optionally call
ClientConnectionManager#closeIdleConnections() method to close all
connections that have been idle over a given period of time.
... end snippet ...
Today we implement both the stale connection checking as well as the
IdleConnectionTimeoutThread (in 3.1).
I would love to save the 10-30ms overhead but without doing that
stale check it is possible that a connection was closed (that the
Idle monitor may not have awoken to catch)..
Sounds like to me the only way to be as close to 100% safe is to
implement both..
Is that correct?
I don't believe so.
Assuming the connection is stale, then you'll get an exception when
you try to use it, so assuming you have a retry handler installed, you
can automatically retry that type of failure.
Some code from the Bixo project to illustrate:
_httpClient = new DefaultHttpClient(cm, params);
_httpClient.setHttpRequestRetryHandler(new
MyRequestRetryHandler(MAX_RETRY_COUNT));
private static class MyRequestRetryHandler implements
HttpRequestRetryHandler {
private int _maxRetryCount;
public MyRequestRetryHandler(int maxRetryCount) {
_maxRetryCount = maxRetryCount;
}
@Override
public boolean retryRequest(IOException exception, int
executionCount, HttpContext context) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Decide about retry #" + executionCount
+ " for exception " + exception.getMessage());
}
if (executionCount >= _maxRetryCount) {
// Do not retry if over max retry count
return false;
} else if (exception instanceof NoHttpResponseException) {
// Retry if the server dropped connection on us
return true;
} else if (exception instanceof SSLHandshakeException) {
// Do not retry on SSL handshake exception
return false;
}
HttpRequest request =
(HttpRequest)context.getAttribute(ExecutionContext.HTTP_REQUEST);
boolean idempotent = !(request instanceof
HttpEntityEnclosingRequest);
// Retry if the request is considered idempotent
return idempotent;
}
}
--------------------------------------------
Ken Krugler
+1 530-210-6378
http://bixolabs.com
e l a s t i c w e b m i n i n g