简体   繁体   English

Apache HttpClient - 需要使用MultiThreadedHttpConnectionManager吗?

[英]Apache HttpClient - Need to use MultiThreadedHttpConnectionManager?

I have server which receives requests from clients and based on the requests connects to some external website & does some operations. 我有服务器接收来自客户端的请求,并根据请求连接到一些外部网站并执行一些操作。

I am using Apache Commons HttpClient (v 2.0.2) to do these connections (I know it's old, but I have to use it because of other restrictions). 我正在使用Apache Commons HttpClient (v 2.0.2)来进行这些连接(我知道它已经过时了,但由于其他限制我必须使用它)。

My server is not going to get frequent requests. 我的服务器不会经常请求。 I think it may be a lot of requests when it's first deployed. 我认为首次部署时可能会有很多请求。 Then on it's only going to be a few requests a day. 然后它只会是一天的几个请求。 There may be occasional spurts when again there are a lot of requests occasionally. 偶尔会有很多请求可能会偶尔发生冲突。

All connections are going to be one of 3 URLS - they may be http or https 所有连接都将是3个URL之一 - 它们可能是http或https

I was thinking of using separate instances of HttpClient for each request 我想为每个请求使用HttpClient单独实例

Is there any need for me to use a common HttpClient object & use it with MultiThreadedHttpConnectionManager for different connections. 是否需要使用常见的HttpClient对象并将其与MultiThreadedHttpConnectionManager用于不同的连接。 How exactly does MultiThreadedHttpConnectionManager help - does it keep the connection open even after you call releaseConnection? MultiThreadedHttpConnectionManager究竟是如何帮助的 - 即使在调用releaseConnection之后它是否保持连接打开? How long will it keep it open? 它会保持打开多长时间?

All my connections are going to be GET & they are going to return 10-20 bytes at most. 我所有的连接都将是GET,它们最多将返回10-20个字节。 I am not downloading anything. 我没有下载任何东西。 The reason I am using HttpClient rather than core java libraries is because occasionally, I may want to use HTTP 1.0 (I don't think java classes support this) and I also may want to do Http Redirects automatically. 我使用HttpClient而不是核心java库的原因是偶尔,我可能想使用HTTP 1.0(我不认为java类支持这个),我也可能想要自动执行Http Redirects。

I use a PoolingHttpClientConnectionManager in a considerably multi-threaded environment and it works very well. 我在一个相当多线程的环境中使用PoolingHttpClientConnectionManager ,它运行得很好。

Here's an implementation of a Client pool: 这是客户端池的实现:

public class HttpClientPool {

    // Single-element enum to implement Singleton.
    private static enum Singleton {

        // Just one of me so constructor will be called once.

        Client;
        // The thread-safe client.
        private final CloseableHttpClient threadSafeClient;
        // The pool monitor.
        private final IdleConnectionMonitor monitor;

        // The constructor creates it - thus late
        private Singleton() {
            PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
            // Increase max total connection to 200
            cm.setMaxTotal(200);
            // Increase default max connection per route to 200
            cm.setDefaultMaxPerRoute(200);

            // Make my builder.
            HttpClientBuilder builder = HttpClients.custom()
                    .setRedirectStrategy(new LaxRedirectStrategy())
                    .setConnectionManager(cm);
            // Build the client.
            threadSafeClient = builder.build();
            // Start up an eviction thread.
            monitor = new IdleConnectionMonitor(cm);
            // Start up the monitor.
            Thread monitorThread = new Thread(monitor);
            monitorThread.setDaemon(true);
            monitorThread.start();
        }

        public CloseableHttpClient get() {
            return threadSafeClient;
        }

    }

    public static CloseableHttpClient getClient() {
        // The thread safe client is held by the singleton.
        return Singleton.Client.get();
    }

    public static void shutdown() throws InterruptedException, IOException {
        // Shutdown the monitor.
        Singleton.Client.monitor.shutdown();
    }

    // Watches for stale connections and evicts them.
    private static class IdleConnectionMonitor implements Runnable {

        // The manager to watch.

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

        IdleConnectionMonitor(PoolingHttpClientConnectionManager cm) {
            this.cm = cm;
        }

        public void run() {
            try {
                // Holds the stop request that stopped the process.
                Stop stopRequest;
                // Every 5 seconds.
                while ((stopRequest = stopSignal.poll(5, TimeUnit.SECONDS)) == null) {
                    // Close expired connections
                    cm.closeExpiredConnections();
                    // Optionally, close connections that have been idle too long.
                    cm.closeIdleConnections(60, 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();
            }

        }

        public void shutdown() throws InterruptedException, IOException {
            // Signal the stop to the thread.
            Stop stop = new Stop();
            stopSignal.add(stop);
            // Wait for the stop to complete.
            stop.waitForStopped();
            // Close the pool.
            HttpClientPool.getClient().close();
            // Close the connection manager.
            cm.close();
        }

    }

}

All you need to do is CloseableHttpResponse conversation = HttpClientPool.getClient().execute(request); 您需要做的就是CloseableHttpResponse conversation = HttpClientPool.getClient().execute(request); and when you've finished with it, just close it and it will be returned to the pool. 当你完成它,只需close它,它将返回到池中。

I think it all depends on what your SLAs are and if the the performance is within the acceptable/expected response times. 我认为这完全取决于您的SLA是什么以及性能是否在可接受/预期的响应时间内。 Your solution will work without any issues but it is not scalable if your application demands grow over time. 您的解决方案可以正常运行,但如果您的应用程序需求随着时间的推移而不可扩展

Using MultiThreadedHttpConnectionManager is much more elegant/scalable solution than having to manage 3 independent HttpClient objects. 使用MultiThreadedHttpConnectionManager比管理3个独立的HttpClient对象更加优雅/可扩展。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM