Frage

Für eine Weile Ich habe mit Httpclient in einer Multithread-Umgebung. Für jeden Thread, wenn er eine Verbindung einleitet, wird es eine völlig neue Httpclient-Instanz erstellen.

Vor kurzem habe ich entdeckt, dass durch diesen Ansatz verwendet, kann es der Benutzer verursachen zu viele Ports zu haben, geöffnet, und die meisten der Verbindungen sind in TIME_WAIT Zustand.

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

Daher statt jeden Thread ausführen:

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

Wir planen, haben:

[Verfahren A]

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

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

In einer normalen Situation, global_c wird gleichzeitig von 50 ++ Threads zugegriffen werden. Ich habe mich gefragt, wird dies keine Performance-Probleme schaffen? Ist MultiThreadedHttpConnectionManager mit einem Lock-Free-Mechanismus seine Threadsicherheit Politik umzusetzen?

Wenn 10 Threads global_c verwenden, werden die anderen 40 Threads gesperrt werden?

Oder wäre es besser, wenn in jedem Thread, ich eine Instanz eines Httpclient erstellen, aber lassen Sie den Verbindungs-Manager explizit?

[Verfahren B]

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

Wird connman.shutdown () Performance-Problemen leiden?

Darf ich wissen, welche Methode (A oder B) ist besser für die Anwendung unter Verwendung eines 50 ++ Threads?

War es hilfreich?

Lösung 2

Methode A wird von Httpclient-Entwickler-Community empfohlen.

Bitte beachten Sie http: //www.mail- archive.com/httpclient-users@hc.apache.org/msg02455.html für weitere Details.

Andere Tipps

Definitiv Verfahren A, weil sein gepoolt und threadsicher.

Wenn Sie Httpclient 4.x verwenden, wird der Verbindungs-Manager namens ThreadSafeClientConnManager . Sehen Sie diesen Link für weitere Details (nach unten scrollen zu " Pooling-Verbindungs-Manager "). Zum Beispiel:

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

Meine Lektüre der Dokumente ist, dass Httpconnection mich nicht als Thread-sicher behandelt wird, und somit MultiThreadedHttpConnectionManager bietet eine wiederverwendbare Pool von HttpConnections, haben Sie einen einzelner MultiThreadedHttpConnectionManager von allen Threads gemeinsam und genau einmal initialisiert. Sie müssen also ein paar kleine Verfeinerungen Option A.

MultiThreadedHttpConnectionManager connman = new MultiThreadedHttpConnectionManag

Dann sollte jeder Thread für jede Anforderung unter Verwendung der Sequenz sein, die Verbindung aus dem Pool und es zurück nach Abschluss seiner Arbeit setzen - einen finally-Block verwendet, kann gut sein. Sie sollten auch den Code für die Möglichkeit, dass der Pool keine verfügbaren Verbindungen hat und die Timeout-Ausnahme verarbeiten.

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

Wie Sie einen Pool von Verbindungen verwenden, werden Sie nicht tatsächlich die Verbindungen werden geschlossen und so soll dies das TIME_WAIT Problem nicht betroffen. Dieser Ansatz macht assuume, dass jeder Faden hängt nicht mit dem Anschluss für lange. Beachten Sie, dass conman selbst offen gelassen wird.

Ich glaube, Sie wollen ThreadSafeClientConnManager verwenden.

Sie können sehen, wie es funktioniert hier: http: //foo.jasonhudgins.com/2009/08/http-connection-reuse-in-android.html

oder im AndroidHttpClient, die es intern verwendet.

Mit Httpclient 4.5 können Sie dies tun:

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

Beachten Sie, dass dies ein implementiert Verschließbare (zum Abschalten des Verbindungs-Manager).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top