문제

한동안 저는 멀티스레드 환경에서 HttpClient를 사용해왔습니다.모든 스레드에 대해 연결을 시작하면 완전히 새로운 HttpClient 인스턴스가 생성됩니다.

최근에 저는 이 접근 방식을 사용하면 사용자가 너무 많은 포트를 열 수 있고 대부분의 연결이 TIME_WAIT 상태에 있다는 사실을 발견했습니다.

http://www.opensubscriber.com/message/commons-httpclient-dev@jakarta.apache.org/86045.html

따라서 각 스레드 대신 다음을 수행합니다.

HttpClient c = new HttpClient();
try {
    c.executeMethod(method);
}
catch(...) {
}
finally {
    method.releaseConnection();
}

우리는 다음을 계획하고 있습니다:

[방법A]

// global_c is initialized once through
// HttpClient global_c = new HttpClient(new MultiThreadedHttpConnectionManager());

try {
    global_c.executeMethod(method);
}
catch(...) {
}
finally {
    method.releaseConnection();
}

일반적인 상황에서는 50++ 스레드가 동시에 global_c에 액세스합니다.이것이 성능 문제를 일으킬 수 있는지 궁금합니다.MultiThreadedHttpConnectionManager는 스레드 안전 정책을 구현하기 위해 잠금 없는 메커니즘을 사용하고 있습니까?

10개의 스레드가 global_c를 사용하는 경우 나머지 40개의 스레드는 잠기나요?

아니면 모든 스레드에서 HttpClient의 인스턴스를 생성하지만 연결 관리자를 명시적으로 해제하는 것이 더 좋을까요?

[방법B]

MultiThreadedHttpConnectionManager connman = new MultiThreadedHttpConnectionManager();
HttpClient c = new HttpClient(connman);
try {
      c.executeMethod(method);
}
catch(...) {
}
finally {
    method.releaseConnection();
    connman.shutdown();
}

connman.shutdown()에 성능 문제가 발생합니까?

50++ 스레드를 사용하는 응용 프로그램에 대해 어떤 방법(A 또는 B)이 더 좋은지 알 수 있습니까?

도움이 되었습니까?

해결책 2

방법 A는 HttpClient 개발자 커뮤니티에서 권장합니다.

참조하시기 바랍니다 http://www.mail-archive.com/httpclient-users@hc.apache.org/msg02455.html 자세한 사항은.

다른 팁

풀링되고 스레드가 안전하기 때문에 확실히 방법 A.

httpclient 4.x를 사용하는 경우 연결 관리자가 ThreadSafeClientConnmanager. 이것 좀 봐 링크 자세한 내용은 "풀링 연결 관리자"로 스크롤). 예를 들어:

    HttpParams params = new BasicHttpParams();
    SchemeRegistry registry = new SchemeRegistry();
    registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    ClientConnectionManager cm = new ThreadSafeClientConnManager(params, registry);
    HttpClient client = new DefaultHttpClient(cm, params);

내가 읽은 문서에 따르면 HttpConnection 자체는 스레드로부터 안전한 것으로 처리되지 않으므로 MultiThreadedHttpConnectionManager는 재사용 가능한 HttpConnections 풀을 제공합니다. 모든 스레드에서 공유되고 정확히 한 번 초기화되는 단일 MultiThreadedHttpConnectionManager가 있습니다.따라서 옵션 A에 대해 몇 가지 작은 개선이 필요합니다.

MultiThreadedHttpConnectionManager connman = new MultiThreadedHttpConnectionManag

그런 다음 각 스레드는 모든 요청에 ​​대해 시퀀스를 사용해야 하며 풀에서 연결을 가져와 작업 완료 시 다시 연결해야 합니다. finally 블록을 사용하는 것이 좋을 수 있습니다.또한 풀에 사용 가능한 연결이 없을 가능성에 대해 코딩하고 시간 초과 예외를 처리해야 합니다.

HttpConnection connection = null
try {
    connection = connman.getConnectionWithTimeout(
                        HostConfiguration hostConfiguration, long timeout) 
    // work
} catch (/*etc*/) {/*etc*/} finally{
    if ( connection != null )
        connman.releaseConnection(connection);
}

연결 풀을 사용하면 실제로 연결이 닫히지 않으므로 TIME_WAIT 문제가 발생하지 않습니다.이 접근 방식은 각 스레드가 오랫동안 연결을 유지하지 않는다고 가정합니다.conman 자체는 열려 있는 상태로 유지됩니다.

ThreadSafeClientConnmanager를 사용하고 싶다고 생각합니다.

여기에서 어떻게 작동하는지 볼 수 있습니다. http://foo.jasonhudgins.com/2009/08/http-connection-reuse-in-1-htroid.html

또는 AndroidHttpClient 내부적으로 사용합니다.

httpclient 4.5를 사용하면 다음을 수행 할 수 있습니다.

CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(new PoolingHttpClientConnectionManager()).build();

이 하나는 닫을 수 있습니다 (연결 관리자의 종료를 위해).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top