Çok İş Parçacıklı Ortamda HttpClient Kullanmak İçin En İyi Uygulama


85

Bir süredir, çok iş parçacıklı bir ortamda HttpClient kullanıyorum. Her iş parçacığı için bir bağlantı başlattığında tamamen yeni bir HttpClient örneği oluşturacaktır.

Son zamanlarda, bu yaklaşımı kullanarak, kullanıcının çok fazla bağlantı noktasına sahip olmasına ve bağlantıların çoğunun TIME_WAIT durumunda olmasına neden olabileceğini keşfettim.

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

Dolayısıyla, her iş parçacığı yerine:

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

Sahip olmayı planlıyoruz:

[YÖNTEM A]

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

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

Normal bir durumda, global_c'ye 50 ++ evre ile eşzamanlı olarak erişilecektir. Merak ediyordum, bu herhangi bir performans sorunu yaratır mı? MultiThreadedHttpConnectionManager, iş parçacığı güvenli ilkesini uygulamak için kilitsiz bir mekanizma kullanıyor mu?

10 iş parçacığı global_c kullanıyorsa, diğer 40 iş parçacığı kilitlenecek mi?

Ya da her iş parçacığında bir HttpClient örneği oluşturup bağlantı yöneticisini açık bir şekilde serbest bırakırsam daha iyi olur mu?

[YÖNTEM B]

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

Connman.shutdown () performans sorunları yaşar mı?

50 ++ iş parçacığı kullanan uygulama için hangi yöntemin (A veya B) daha iyi olduğunu öğrenebilir miyim?

Yanıtlar:


47

Kesinlikle Yöntem A, çünkü havuza alınmış ve iş parçacığı güvenli.

Httpclient 4.x kullanıyorsanız, bağlantı yöneticisine ThreadSafeClientConnManager adı verilir . Daha fazla ayrıntı için bu bağlantıya bakın ("Havuz bağlantısı yöneticisi" ne gidin). Örneğin:

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

49
ThreadSafeClientConnManager , 4.2'de PoolingClientConnManager lehine kullanımdan kaldırıldı
Drew Stephens

Merhaba, bu yöntemle oluşturulan httpclient, burada stackoverflow.com/questions/5960832/… ... açıklandığı gibi oturumu sürdürmek için kullanılabilir mi? Çünkü denediğimde, farklı isteklerde oturumu
sürdüremedim

17
4.3.1 burada: PoolingClientConnManager, PoolingHttpClientConnectionManager lehine kullanımdan kaldırıldı.
Matthias

@DrewStephens Again PoolingClientConnManager, PoolingHttpClientConnectionManager lehine kullanımdan kaldırıldı
didxga

18

A Yöntemi, httpclient geliştirici topluluğu tarafından önerilir.

Daha fazla ayrıntı için lütfen http://www.mail-archive.com/httpclient-users@hc.apache.org/msg02455.html bakın .


1
İstemci global hale getirilirse, bir bağlantı yöneticisinde ne zaman "kapat" çağrısı yapılır.
Wand Maker

1
Başlık altındaki ConnectionManager'ın davranışında hata ayıklamak veya "görselleştirmek" için hangi araçlar / linux komutları kullanışlıdır? Şu anda CLOSE_WAIT ve diğer efektlerdeki bağlantılarla ilgili sorun yaşadığımız ve tam olarak ne olup bittiğini görmenin iyi bir yolunu bulmaya çalıştığımız için soruyorum.
Christoph

@WandMaker Programdan çıktığında veya bir süre bağlantıya ihtiyaç duymayacağınız bazı toplu işlerle işiniz bittiğinde, sadece kapatmayı çağıracağınızdan oldukça eminim.
Nicholas DiPiazza

1
@Christoph bunda netstatgerçekten iyi bir iş çıkarıyor. technet.microsoft.com/en-us/sysinternals/bb897437.aspx çok
Nicholas DiPiazza

13

Belgeleri okudum, HttpConnection'ın kendisinin iş parçacığı için güvenli olarak değerlendirilmediği ve dolayısıyla MultiThreadedHttpConnectionManager'ın yeniden kullanılabilir bir HttpConnections havuzu sağladığı, tüm iş parçacıkları tarafından paylaşılan ve tam olarak bir kez başlatılan tek bir MultiThreadedHttpConnectionManager var. Bu nedenle, A seçeneği için birkaç küçük düzeltmeye ihtiyacınız var.

MultiThreadedHttpConnectionManager connman = new MultiThreadedHttpConnectionManag

Daha sonra her iş parçacığı, her istek için diziyi kullanmalı, havuzdan bir bağlantı almalı ve işinin tamamlanmasına geri koymalıdır - bir nihayet bloğu kullanmak iyi olabilir. Ayrıca havuzda kullanılabilir bağlantı olmaması olasılığını da kodlamanız ve zaman aşımı istisnasını işlemeniz gerekir.

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

Bir bağlantı havuzu kullandığınızda, aslında bağlantıları kapatmayacaksınız ve bu nedenle bu TIME_WAIT sorununu çözmemelidir. Bu yaklaşım, her iş parçacığının bağlantıya uzun süre bağlı kalmayacağını varsayar. Conman'ın kendisinin açık bırakıldığını unutmayın.


Soruma gerçek bir cevap gelmedi, hangi yöntemin (A veya B) daha iyi olduğu.
Cheok Yan Cheng


5

HttpClient 4.5 ile bunu yapabilirsiniz:

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

Bunun Kapatılabilir uyguladığını unutmayın (bağlantı yöneticisini kapatmak için).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.