axis-java-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Manny Lim (JIRA)" <j...@apache.org>
Subject [jira] Created: (AXIS2-3945) Threading issue in AbstractHTTPSender
Date Fri, 25 Jul 2008 22:35:31 GMT
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


Mime
View raw message