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