2014-09-04 3 views
3

클라이언트로부터 요청을 받고 요청에 따라 일부 외부 웹 사이트에 연결하는 서버가 있습니다 & 일부 작업을 수행합니다.Apache HttpClient - MultiThreadedHttpConnectionManager를 사용해야합니까?

이러한 연결을 수행하기 위해 Apache Commons HttpClient (v 2.0.2)을 사용하고 있습니다. 이전 버전이지만 다른 제한 사항 때문에 사용해야합니다.

내 서버가 자주 요청하지 않습니다. 처음 배포 할 때 많은 요청이 될 것으로 생각합니다. 그렇다면 하루에 몇 가지 요청 만있을 것입니다. 때때로 다시 요청이 많이있을 때가끔 발생합니다.

모든 연결은 3 개 URL이 중 하나가 될거야 - 그들은 HTTP 또는 HTTPS

나는 각 요청

에 대한 HttpClient의 개별 인스턴스를 사용하는 생각을 할 수있다 나에게를 사용하는을 위해 어떤 필요가 공통 HttpClient 오브젝트 &은 서로 다른 연결에 대해 MultiThreadedHttpConnectionManager과 함께 사용하십시오. MultiThreadedHttpConnectionManager는 정확히 어떻게 도움이됩니까? releaseConnection을 호출 한 후에도 연결을 유지합니까? 얼마나 오랫동안 열어 둘 수 있습니까?

모든 연결은 GET &이 될 것입니다. 최대 10-20 바이트를 반환 할 것입니다. 나는 아무것도 다운로드하지 않고있다. 핵심 자바 라이브러리가 아닌 HttpClient을 사용하는 이유는 가끔씩 HTTP 1.0 (자바 클래스가 지원하지 않는다고 생각하기 때문에)을 사용하고 HTTP 리디렉션을 자동으로 수행하기를 원하기 때문입니다.

+1

http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html을 확인하십시오.이 질문에 대한 자세한 답변을 제공합니다. –

답변

0

상당한 멀티 스레드 환경에서 PoolingHttpClientConnectionManager을 사용하며 매우 잘 작동합니다.

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(); 
     } 

    } 

} 

당신이해야 할 모든 CloseableHttpResponse conversation = HttpClientPool.getClient().execute(request); 그리고 당신은 단지 close을, 그것으로 마무리 한 때 풀에 반환됩니다

다음은 클라이언트 풀의 구현입니다.

+0

HttpClient의 이전 버전을 사용하고 있습니다. 지원되지 않는다고 생각합니다. 또한, 내 질문은 내가 연결 풀링이나 관리가 정말로 필요한지에 관한 것입니다. – user93353

0

SLA가 무엇이고 성능이 허용 가능한/예상 응답 시간 내에 있는지에 따라 달라집니다. 솔루션은 아무 문제없이 작동하지만 시간이 지남에 따라 애플리케이션 요구 사항이 증가하면 확장 성이 없습니다.

MultiThreadedHttpConnectionManager을 사용하면 3 개의 독립적 인 HttpClient 객체를 관리해야하는 것보다 훨씬 더 우아하고 확장 가능한 솔루션입니다.

+0

3 개의 HttpClient 객체를 관리하지 않을 것입니다. 내 스레드 함수는 단 1 HttpClient 개체를 갖습니다. 그러나 한 번에 하나 이상의 쓰레드가 실행됩니다. – user93353

+0

db, jms 또는 http가 값 비싼 작업인지 여부에 관계없이 연결 만들기. 이 경우이 스레드 함수에서 매번 HttpClient (연결)를 작성합니다. 아니면 모든 스레드에서 공유되는 HttpClient 인스턴스가 하나만 있다고 말하는 것입니까? 알려줘. 감사. – Kalyan

+0

releaseConnection을 호출 한 후 MultiThreadedHttpConnectionManager가 연결을 유지하는 기간입니다. – user93353

관련 문제