PoolingHttpClientConnectionManager не выполняет параллельные запросы - PullRequest
0 голосов
/ 14 февраля 2019

Я использую Spring WebServiceTemplate Apache HttpClient (4.5.3) для выполнения запроса на мыло одному из моих клиентов.Я хочу делать много асинхронных запросов и обрабатывать ответ всякий раз, когда получаю его.

Моя стратегия заключается в том, чтобы использовать один PoolingHttpClientConnectionManager и делать HttpClientBuilder.setConnectionManager(connectionManager).build() для каждого запроса.

Но под нагрузкой время отклика начинает замедляться!Я проверил, что клиент все еще отвечает быстро, но sendSourceAndReceiveToResult слишком долго говорит.Чтобы выяснить, что происходит, я зарегистрировал connectionManager stats, вот что я получил:

connectionManager.getTotalStats().getAvailable() --> 40
connectionManager.getTotalStats().getLeased()    --> 1 only one connection is used to request!
connectionManager.getMaxTotal()                  --> 200
connectionManager.getDefaultMaxPerRoute()        --> 200

Вот мое определение бина

<bean id="myMessageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory" />

<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
    <constructor-arg ref="myMessageFactory" />
    <property name="messageSender" ref="messageSender"></property>
</bean>

<bean id="messageSender" class="org.springframework.ws.transport.http.HttpComponentsMessageSender"
</bean>

Мой менеджер соединений

public class CustomPoolingHttpClientConnectionManager extends PoolingHttpClientConnectionManager {

    private IdleConnectionMonitorThread monitor;

    Logger logger = LoggerFactory.getLogger(CustomPoolingHttpClientConnectionManager.class);


    private static final class ConnectionManagerInstanceHolder {
        private static final CustomPoolingHttpClientConnectionManager instance = new CustomPoolingHttpClientConnectionManager();
    }

    private static Registry<ConnectionSocketFactory> getSocketFactoryRegistry() {

        SSLConnectionSocketFactory socketFactory = null;
        try {
            SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(
                    new File(System.getProperty("javax.net.ssl.keyStore")),
                    System.getProperty("javax.net.ssl.keyStorePassword").toCharArray(),
                    System.getProperty("javax.net.ssl.keyStorePassword").toCharArray()).build();

            socketFactory = new SSLConnectionSocketFactory(
                    sslcontext,
                    new String[]{"TLSv1"},
                    null,
                    SSLConnectionSocketFactory.getDefaultHostnameVerifier());
        }
        catch (Exception ex) {
            //
        }

        return RegistryBuilder.<ConnectionSocketFactory> create()
                .register("https", socketFactory)
                .build();
    }

    public static CustomPoolingHttpClientConnectionManager getInstance() {
        return ConnectionManagerInstanceHolder.instance;
    }

    public CustomPoolingHttpClientConnectionManager() {
        super ( getSocketFactoryRegistry() );

        monitor = new IdleConnectionMonitorThread(this);
        monitor.start();
    }


 // Watches for stale connections and evicts them.
    private static class IdleConnectionMonitorThread extends Thread {

        Logger logger = LoggerFactory.getLogger(IdleConnectionMonitorThread.class);

        // The manager to watch.
        private final PoolingHttpClientConnectionManager connectionManager;
        // Use a BlockingQueue to stop everything.
        private final BlockingQueue<Stop> stopSignal = new ArrayBlockingQueue<Stop>(1);

        IdleConnectionMonitorThread(PoolingHttpClientConnectionManager cm) {
            super();
            this.connectionManager = cm;
        }

        @Override
        public void run() {
            try {
                // Holds the stop request that stopped the process.
                Stop stopRequest;

                connectionManager.setMaxTotal(200);
                connectionManager.setDefaultMaxPerRoute(200);

                // Every 5 seconds.
                while ((stopRequest = stopSignal.poll(5, TimeUnit.SECONDS)) == null) {
                    logger.debug("Available Threads: " + connectionManager.getTotalStats().getAvailable() +
                                 "\nCurrently Working Threads: " + connectionManager.getTotalStats().getLeased() + 
                                 "\nTotal Thread count: " + connectionManager.getMaxTotal() +
                                 "\nMax Thread per host: " + connectionManager.getDefaultMaxPerRoute());
                    // Close expired connections
                    connectionManager.closeExpiredConnections();
                    // Optionally, close connections that have been idle too long.
                    connectionManager.closeIdleConnections(20, TimeUnit.SECONDS);
                }
                // Acknowledge the stop request.
                stopRequest.stopped();
            } catch (InterruptedException ex) {
                // terminate
            }
        }

        // Pushed up the queue.
        private static class Stop {
            // The return queue.
            private final BlockingQueue<Stop> stop = new ArrayBlockingQueue<Stop>(1);

            // Called by the process that is being told to stop.
            public void stopped() {
                // Push me back up the queue to indicate we are now stopped.
                stop.add(this);
            }

            // Called by the process requesting the stop.
            public void waitForStopped() throws InterruptedException {
                // Wait until the callee acknowledges that it has stopped.
                stop.take();
            }
        }
    }
}

Настройка HttpClient

private CloseableHttpClient buildHttpClient() {

    HttpClientBuilder builder = HttpClientBuilder.create();

    RequestConfig.Builder requestConfig = RequestConfig.custom();
    requestConfig.setSocketTimeout(2000);
    requestConfig.setConnectionRequestTimeout(2000);
    requestConfig.setConnectTimeout(2000);


    builder.setDefaultRequestConfig(requestConfig.build());

    HttpComponentsMessageSender.RemoveSoapHeadersInterceptor interceptor = new HttpComponentsMessageSender.RemoveSoapHeadersInterceptor();
    builder.addInterceptorFirst(interceptor);

    builder.setConnectionManager( CustomPoolingHttpClientConnectionManager.getInstance() )
    .setConnectionManagerShared(true);

    return builder.build();
}

Настройка HttpClient

((HttpComponentsMessageSender) webServiceTemplate.getMessageSenders()[0]).setHttpClient(httpClient);

Я проверяю, закрываю ли CloseableHttpClient после получения ответа.Но я понятия не имею, почему ответы очень медленные!Что я здесь не так делаю?Любая помощь очень ценится!

...