2009-08-15 12 views
78

Od pewnego czasu używam HttpClient w środowisku wielowątkowym. Dla każdego wątku, gdy zainicjuje połączenie, utworzy zupełnie nową instancję HttpClient.Najlepsza praktyka używania HttpClient w środowisku wielowątkowym

Niedawno odkryłem, że za pomocą tego podejścia może to spowodować, że użytkownik będzie miał otwartych zbyt wiele portów, a większość połączeń będzie w stanie TIME_WAIT.

http://www.opensubscriber.com/message/[email protected]/86045.html

Stąd, zamiast każda nić sposób:

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

Planujemy:

[Metoda A]

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

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

W normalnej sytuacji, global_c będzie dostępny jednocześnie przez 50 wątków. Zastanawiam się, czy spowoduje to problemy z wydajnością? Czy MultiThreadedHttpConnectionManager używa mechanizmu blokującego, aby wdrożyć politykę bezpieczeństwa wątków?

Jeśli 10 wątków korzysta z global_c, czy pozostałe 40 wątków zostanie zablokowanych?

A może byłoby lepiej, gdyby w każdym wątku utworzyć wystąpienie HttpClient, ale zwolnić menedżera połączeń jawnie?

[Metoda B]

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

Will connman.shutdown() cierpią problemy z wydajnością?

Czy mogę wiedzieć, która metoda (A lub B) jest lepsza, dla aplikacji używającej wątków 50 ++?

Odpowiedz

16

Metoda A jest zalecana przez społeczność programistów httpclient.

Aby uzyskać więcej informacji, zapoznaj się z http://www.mail-archive.com/[email protected]e.org/msg02455.html.

+1

Kiedy zostanie wywołane "zamknięcie" w menedżerze połączeń, jeśli klient jest globalny. –

+1

Które narzędzia/komendy linuksowe są przydatne do debugowania lub "wizualizowania" zachowania menedżera połączeń pod maską? Pytam, ponieważ mamy obecnie problemy z połączeniami w CLOSE_WAIT i innymi efektami, i walczymy o znalezienie dobrego sposobu, aby zobaczyć, co się właściwie dzieje. – Christoph

+0

@WandMaker Jestem prawie pewny, że po prostu zadzwonisz do wyłączenia, gdy któryś z programów wyjdzie lub gdy skończysz z jakąś partią pracy, w której przez jakiś czas nie będziesz potrzebował żadnych połączeń. –

12

Moje czytanie docs jest to, że httpconnection sama nie jest traktowany jako bezpieczny wątku, a więc MultiThreadedHttpConnectionManager zapewnia wielokrotnego użytku pula HttpConnections, masz jeden MultiThreadedHttpConnectionManager współdzielony przez wszystkie gwinty i zainicjowany dokładnie raz. Więc trzeba kilka drobnych udoskonaleń do opcji A.

MultiThreadedHttpConnectionManager connman = new MultiThreadedHttpConnectionManag 

Następnie każdy wątek powinien być przy użyciu sekwencji dla każdego żądania, coraz conection z basenem i oddanie go z powrotem po zakończeniu jego pracy - za pomocą wreszcie blok może być dobry. Powinieneś również zakodować, że pula nie ma dostępnych połączeń i przetworzyć wyjątek limitu czasu.

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

Jak używasz pulę połączeń nie będzie faktycznie zamknięcie połączenia i tak nie powinno trafić problem CZAS_OCZEKIWANIA. To podejście zakłada, że ​​każdy wątek nie będzie długo zawieszony na połączeniu. Zauważ, że conman sam jest otwarty.

+0

Nie odpowiedziałem na moje pytanie, która metoda (A lub B) jest lepsza. –

+4

Odpowiedź była taka, że ​​żadna z nich nie jest poprawna. Wyjaśnię to. – djna

5

Myślę, że będziesz chciał użyć ThreadSafeClientConnManager.

Można zobaczyć, jak to działa tutaj: http://foo.jasonhudgins.com/2009/08/http-connection-reuse-in-android.html

Lub w AndroidHttpClient który wykorzystuje go wewnętrznie.

+1

Opps. Nie planuję migracji z HttpClient 3.x do 4.x, ponieważ 3.x działał bezbłędnie w mojej aplikacji przez prawie 2 lata :) –

+9

Oczywiście, jeśli ktoś tu przyszedł, szukając odpowiedzi :) –

41

Zdecydowanie Metoda A, ponieważ jest połączona i bezpieczna dla wątków.

Jeśli korzystasz z httpclient 4.x, menedżer połączeń nazywa się ThreadSafeClientConnManager. Więcej szczegółowych informacji można znaleźć w link (przewiń w dół do "Menedżer połączeń pulpitowych"). Na przykład:

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); 
+44

[ThreadSafeClientConnManager ] (http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/conn/tsccm/ThreadSafeClientConnManager.html) został przestarzały na rzecz [PoolingClientConnManager] (http: //hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/conn/PoolingClientConnectionManager.html) w 4.2 –

+0

Witam, czy użytkownik httpclient utworzony za pomocą tej metody może być używany do utrzymywania sesji jako opisane tutaj http://stackoverflow.com/questions/5960832/maintaining-session-in-android-application-stay-authenticated-on-the-server-si ...? Ponieważ kiedy próbowałem, nie byłem w stanie utrzymać sesji dla różnych żądań ... – sakthig

+11

4.3.1 tutaj: PoolingClientConnManager został wycofany na rzecz PoolingHttpClientConnectionManager. – Matthias

0

Z HttpClient 4.5 można to zrobić:

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

pamiętać, że ten jeden implementuje zamykany (do wyłączania z menedżer połączeń).

Powiązane problemy