Question

Pendant un certain temps, je l'ai utilisé HttpClient dans un environnement multithread. Pour chaque fil, quand il établit une connexion, il va créer une toute nouvelle instance de HttpClient.

Récemment, je l'ai découvert que, en utilisant cette approche, il peut causer à l'utilisateur d'avoir trop de ports en cours d'ouverture, et la plupart des connexions sont dans un état TIME_WAIT.

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

Par conséquent, au lieu de chaque fil Doing:

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

Nous prévoyons d'avoir:

[Procédé A]

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

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

Dans une situation normale, global_c sera accessible par 50 ++ threads simultanément. Je me demandais, cela créera des problèmes de performance? MultiThreadedHttpConnectionManager utilise un mécanisme sans verrouillage pour mettre en œuvre sa politique fil en toute sécurité?

Si 10 threads utilisent global_c, seront les autres 40 fils être verrouillés?

Ou serait-il mieux si, dans chaque thread, je crée une instance d'un HttpClient, mais libérer le gestionnaire de connexion explicitement?

[PROCEDE B]

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

Est-ce que connman.shutdown () souffrent des problèmes de performance?

Puis-je savoir quelle méthode (A ou B) est préférable, pour une application en utilisant un fils de 50 ++?

Était-ce utile?

La solution 2

Méthode A est recommandée par la communauté des développeurs httpclient.

S'il vous plaît consulter http: //www.mail- archive.com/httpclient-users@hc.apache.org/msg02455.html pour plus de détails.

Autres conseils

Sans aucun doute la méthode A et parce que son thread-safe mis en commun.

Si vous utilisez 4.x httpclient, le gestionnaire de connexion est appelé ThreadSafeClientConnManager . Voir cette pour plus de détails (faites défiler jusqu'à " mettre en commun le gestionnaire de connexion "). Par exemple:

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

Ma lecture des documents est que HttpConnection lui-même est pas traité comme thread-safe, et donc MultiThreadedHttpConnectionManager dispose d'une piscine réutilisable de HttpConnections, vous avez un seul MultiThreadedHttpConnectionManager partagé par tous les threads et initialisés exactement une fois. Vous avez donc besoin d'un couple de petits raffinements à l'option A.

MultiThreadedHttpConnectionManager connman = new MultiThreadedHttpConnectionManag

Ensuite, chaque fil devrait utiliser la séquence pour chaque demande, obtenir un conection de la piscine et de le remettre à la fin de ses travaux - en utilisant un bloc finally peut être bon. Vous devriez écrire aussi la possibilité que la piscine n'a pas de lien disponible et traiter l'exception de délai d'attente.

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

Comme vous utilisez un pool de connexions, vous ne serez pas en fait fermerons les connexions et donc cela ne devrait pas frapper le problème TIME_WAIT. Cette approche ne assuume que chaque fil ne se bloque pas la connexion longtemps. Notez que arnaqueur lui-même est laissée ouverte.

Je pense que vous voulez utiliser ThreadSafeClientConnManager.

Vous pouvez voir comment cela fonctionne ici: http: //foo.jasonhudgins.com/2009/08/http-connection-reuse-in-android.html

Ou dans le AndroidHttpClient qui l'utilise en interne.

Vous pouvez le faire 4,5 HttpClient:

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

Notez que celui-ci met en œuvre Closeable (pour arrêter du gestionnaire de connexion).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top