You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by "Manny Lim (JIRA)" <ji...@apache.org> on 2008/07/26 00:35:31 UTC
[jira] Created: (AXIS2-3945) Threading issue in AbstractHTTPSender
Threading issue in AbstractHTTPSender
-------------------------------------
Key: AXIS2-3945
URL: https://issues.apache.org/jira/browse/AXIS2-3945
Project: Axis 2.0 (Axis2)
Issue Type: Bug
Components: transports
Affects Versions: 1.4
Environment: Axis2/1.4 Java
Reporter: Manny Lim
Priority: Minor
The AbstractHTTPSender method getHttpClient() called by HTTPSender is not thread safe. If an Operation Client performs many non-blocking send/receives, there will be many threads calling this method (the OutInAxisOperationClient creates a NonBlockingInvocationWorker for each one).
Please consider the following situation:
If the options are set as such -
REUSE_HTTP_CLIENT is set to true.
CACHED_HTTP_CLIENT is null (no HttpClient is cached).
Users may expect the OperationClient to use only one HttpClient. However, this is not the case as it is possible that many threads will check the CACHED_HTTP_CLIENT property while it is still null. As a result, each of those threads will create their own HttpClient using their own MultiThreadedHttpConnectionManager, and cache that (overriding any HttpClients that were cached before it). Thus, many HttpClients are used, each with their own MultiThreadedHttpConnectionManager which comes with its own connection pool. A quick netstat will show that many connections are created for the non-blocking send/receives.
I noticed this when performing many non-blocking send/receives ( outInOpClient.execute(false); ) very quickly in succession, with the options specified above. Subsequent non-blocking send/receives perform as expected since the HttpClient has been initialized and cached.
The method copied here for your reference:
protected HttpClient getHttpClient(MessageContext msgContext) {
HttpClient httpClient;
Object reuse = msgContext.getOptions().getProperty(HTTPConstants.REUSE_HTTP_CLIENT);
if (reuse == null) {
reuse = msgContext.getConfigurationContext().getProperty(HTTPConstants.REUSE_HTTP_CLIENT);
}
if (reuse != null && JavaUtils.isTrueExplicitly(reuse)) {
httpClient = (HttpClient) msgContext.getOptions().getProperty(HTTPConstants.CACHED_HTTP_CLIENT);
if (httpClient == null) {
httpClient = (HttpClient) msgContext.getConfigurationContext()
.getProperty(HTTPConstants.CACHED_HTTP_CLIENT);
}
if (httpClient != null)
return httpClient;
MultiThreadedHttpConnectionManager connectionManager =
new MultiThreadedHttpConnectionManager();
httpClient = new HttpClient(connectionManager);
msgContext.getConfigurationContext()
.setProperty(HTTPConstants.CACHED_HTTP_CLIENT, httpClient);
} else {
HttpConnectionManager connManager =
(HttpConnectionManager) msgContext.getProperty(
HTTPConstants.MULTITHREAD_HTTP_CONNECTION_MANAGER);
if (connManager == null) {
connManager =
(HttpConnectionManager) msgContext.getProperty(
HTTPConstants.MUTTITHREAD_HTTP_CONNECTION_MANAGER);
}
if(connManager != null){
httpClient = new HttpClient(connManager);
} else {
//Multi threaded http connection manager has set as the default
connManager = new MultiThreadedHttpConnectionManager();
httpClient = new HttpClient(connManager);
}
}
// Get the timeout values set in the runtime
initializeTimeouts(msgContext, httpClient);
return httpClient;
}
On a side note, why doesn't it check if a cached MultiThreadedHttpConnectionManager exists before creating an HttpClient to cache? It just uses its own. This would allow users more control over the connections and such.
Thanks,
Manny Lim
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
---------------------------------------------------------------------
To unsubscribe, e-mail: axis-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: axis-dev-help@ws.apache.org