HttpClient kapcsolatkezelés

1. Áttekintés

Ebben a cikkben áttekintjük a HttpClient 4 kapcsolatkezelésének alapjait.

Kitérünk a használatára BasichttpClientConnectionManager és PoolingHttpClientConnectionManager a HTTP-kapcsolatok biztonságos, protokollnak megfelelő és hatékony használatának kikényszerítése.

2. A BasicHttpClientConnectionManager alacsony szintű, egy menetes csatlakozáshoz

A BasicHttpClientConnectionManager a HttpClient 4.3.3 óta elérhető, mint a HTTP-kapcsolatkezelő legegyszerűbb megvalósítása. Egyetlen kapcsolat létrehozására és kezelésére szolgál, amelyet egyszerre csak egy szál használhat.

2.1. Példa Csatlakozási kérelem beszerzése alacsony szintű csatlakozáshoz (HttpClientConnection)

BasicHttpClientConnectionManager connManager = új BasicHttpClientConnectionManager (); HttpRoute útvonal = új HttpRoute (új HttpHost ("www.baeldung.com", 80)); ConnectionRequest connRequest = connManager.requestConnection (útvonal, null);

A requestConnection A módszer a menedzsertől kap egy adott kapcsolat kapcsolatait útvonal csatlakozni. A útvonal A paraméter megadja a „proxy ugrás” útvonalát a célállomásig, vagy maga a célállomásig.

Lehetőség van egy kérés végrehajtására egy HttpClientConnection közvetlenül, de ne feledje, hogy ez az alacsony szintű megközelítés bőbeszédű és nehezen kezelhető. Az alacsony szintű kapcsolatok hasznosak a socket és a csatlakozási adatok eléréséhez, például az időkorlátokhoz és a célállomás információkhoz, de a szokásos végrehajtásokhoz a HttpClient egy sokkal könnyebb API, amellyel szemben lehet dolgozni.

3. A PoolingHttpClientConnectionManager többszálas kapcsolatok készletének megszerzése és kezelése

A PoolingHttpClientConnectionManager létrehoz egy kapcsolatkészletet és kezel minden egyes általunk használt útvonalat vagy célgazdát. Az egyidejű készlet alapértelmezett mérete kapcsolatok amelyet a menedzser megnyithat 2 minden útvonalhoz vagy célgazdához, és 20 összesen nyitott kapcsolatok. Először - nézzük meg, hogyan állíthatja be ezt a kapcsolatkezelőt egy egyszerű HttpClient-en:

3.1. Példa A PoolingHttpClientConnectionManager beállítása HttpClienten

HttpClientConnectionManager poolingConnManager = új PoolingHttpClientConnectionManager (); CloseableHttpClient kliens = HttpClients.custom (). SetConnectionManager (poolingConnManager) .build (); client.execute (új HttpGet ("/")); assertTrue (poolingConnManager.getTotalStats (). getLeased () == 1);

Következő - nézzük meg, hogyan használhatja ugyanazt a kapcsolatkezelőt két, különböző szálon futó HttpClients:

3.2. Példa Két HttpClients segítségével csatlakozhat egy-egy célgazdához

HttpGet get1 = új HttpGet ("/"); HttpGet get2 = new HttpGet ("// google.com"); PoolingHttpClientConnectionManager connManager = új PoolingHttpClientConnectionManager (); CloseableHttpClient client1 = HttpClients.custom (). SetConnectionManager (connManager) .build (); CloseableHttpClient client2 = HttpClients.custom (). SetConnectionManager (connManager) .build (); MultiHttpClientConnThread thread1 = új MultiHttpClientConnThread (client1, get1); MultiHttpClientConnThread thread2 = új MultiHttpClientConnThread (client2, get2); thread1.start (); thread2.start (); szál1.csatlakozzon (); szál2.csatlakozzon ();

Figyeljük meg, hogy használjuk egy nagyon egyszerű egyéni szál megvalósítása - itt van:

3.3. Példa Egyéni szál A. Végrehajtása GET kérés

public class MultiHttpClientConnThread kiterjeszti a Thread {private CloseableHttpClient klienst; privát HttpGet get; // standard konstruktorok public void run () {try {HttpResponse response = client.execute (get); EntityUtils.consume (response.getEntity ()); } catch (ClientProtocolException ex) {} catch (IOException ex) {}}}

Figyelje meg aEntityUtils.consume (response.getEntity) hívás - a válasz (entitás) teljes tartalmának elfogyasztásához szükséges, hogy a menedzser megtehesse engedje vissza a kapcsolatot a medencéhez.

4. Konfigurálja a Connection Manager alkalmazást

A pooling kapcsolatkezelő alapértelmezett beállításai jól megválasztottak, de - felhasználási esetétől függően - túl kicsiek lehetnek. Tehát - nézzük meg, hogyan konfigurálhatjuk:

  • a kapcsolatok teljes száma
  • az útvonalakonkénti kapcsolatok maximális száma
  • a kapcsolatok maximális száma egyetlen, meghatározott útvonalon

4.1. Példa Az alapértelmezett korlátokon túl megnyitható és kezelhető kapcsolatok számának növelése

PoolingHttpClientConnectionManager connManager = új PoolingHttpClientConnectionManager (); connManager.setMaxTotal (5); connManager.setDefaultMaxPerRoute (4); HttpHost host = new HttpHost ("www.baeldung.com", 80); connManager.setMaxPerRoute (új HttpRoute (host), 5);

Tegyük át az API-t:

  • setMaxTotal (int max): Állítsa be az összes nyitott kapcsolat maximális számát.
  • setDefaultMaxPerRoute (int max): Állítsa be az egyidejű kapcsolatok maximális számát útvonalonként, amely alapértelmezés szerint 2.
  • setMaxPerRoute (int max): Állítsa be az egyidejű kapcsolatok teljes számát egy adott útvonalhoz, amely alapértelmezés szerint 2.

Tehát az alapértelmezés megváltoztatása nélkül, elérjük a kapcsolatkezelő határait elég könnyen - nézzük meg, hogy néz ki:

4.2. Példa Szálak használata a kapcsolatok végrehajtásához

HttpGet get = new HttpGet ("// www.baeldung.com"); PoolingHttpClientConnectionManager connManager = új PoolingHttpClientConnectionManager (); CloseableHttpClient kliens = HttpClients.custom (). setConnectionManager (connManager) .build (); MultiHttpClientConnThread thread1 = új MultiHttpClientConnThread (kliens, get); MultiHttpClientConnThread thread2 = új MultiHttpClientConnThread (kliens, get); MultiHttpClientConnThread thread3 = új MultiHttpClientConnThread (kliens, get); thread1.start (); thread2.start (); thread3.start (); szál1.csatlakozzon (); szál2.csatlakozzon (); szál3.csatlakozzon ();

Amint már megbeszéltük, az állomásonkénti csatlakozási korlát 2 alapértelmezés szerint. Tehát ebben a példában 3 szálat próbálunk elkészíteni 3 kérés ugyanahhoz a gazdagéphez, de csak 2 kapcsolatot osztanak ki párhuzamosan.

Vessünk egy pillantást a naplókra - három szál fut, de csak 2 bérelt kapcsolat van:

[Thread-0] INFO obhcMultiHttpClientConnThread - Before - Bérelt kapcsolatok = 0 [Thread-1] INFO obhcMultiHttpClientConnThread - Before - Bérelt kapcsolatok = 0 [Thread-2] INFO obhcMultiHttpClientConnThread - 0 - Before - INFO obhcMultiHttpClientConnThread - After - Bérelt kapcsolatok = 2 [Thread-0] INFO obhcMultiHttpClientConnThread - After - Bérelt kapcsolatok = 2

5. Connection Keep-Alive stratégia

Idézi a HttpClient 4.3.3. hivatkozás: „Ha a Életben tartani fejléc nincs a válaszban, HttpClient feltételezi, hogy a kapcsolatot a végtelenségig életben lehet tartani. ” (Lásd a HttpClient referenciát).

Ahhoz, hogy ezt megkerüljük, és képesek legyünk kezelni a holt kapcsolatokat, testreszabott stratégia-megvalósításra van szükségünk, és beépítjük a HttpClient.

5.1. Példa Egyéni életben tartási stratégia

ConnectionKeepAliveStrategy myStrategy = new ConnectionKeepAliveStrategy () {@Orride public long getKeepAliveDuration (HttpResponse response, HttpContext context) {HeaderElementIterator it = new BasicHeaderElementIterator (response.headerIterator (HTTP.Eladó) while (it.hasNext ()) {HeaderElement he = it.nextElement (); Karakterlánc param = he.getName (); Karakterlánc értéke = he.getValue (); if (érték! = null && param.equalsIgnoreCase ("timeout")) {return Long.parseLong (érték) * 1000; }} visszatérés 5 * 1000; }};

Ez a stratégia először megpróbálja alkalmazni a gazdagépet Életben tartani a fejlécben megfogalmazott irányelv. Ha ez az információ nincs a válasz fejlécében, akkor 5 másodpercig életben tartja a kapcsolatokat.

Most - alkossunk kliens ezzel az egyedi stratégiával:

PoolingHttpClientConnectionManager connManager = új PoolingHttpClientConnectionManager (); CloseableHttpClient kliens = HttpClients.custom () .setKeepAliveStrategy (myStrategy) .setConnectionManager (connManager) .build ();

6. A kapcsolat tartóssága / újrafelhasználása

A HTTP / 1.1 Spec azt állítja, hogy a kapcsolatok újból felhasználhatók, ha még nem voltak bezárva - ezt kapcsolati perzisztenciának nevezzük.

Amint a menedzser feloldotta a kapcsolatot, az nyitva marad újrafelhasználás céljából. Ha a BasicHttpClientConnectionManager, amely csak egyetlen kapcsolatot képes elrontani, a kapcsolatot újra fel kell szabadítani, mielőtt újból bérbe adnák:

6.1. Példa BasicHttpClientConnectionManagerKapcsolat újrafelhasználása

BasicHttpClientConnectionManager basicConnManager = új BasicHttpClientConnectionManager (); HttpClientContext context = HttpClientContext.create (); // alacsony szintű HttpRoute útvonal = új HttpRoute (új HttpHost ("www.baeldung.com", 80)); ConnectionRequest connRequest = basicConnManager.requestConnection (útvonal, null); HttpClientConnection conn = connRequest.get (10, TimeUnit.SECONDS); basicConnManager.connect (összeköttetés, útvonal, 1000, kontextus); basicConnManager.routeComplete (kapcsolat, útvonal, kontextus); HttpRequestExecutor exeRequest = új HttpRequestExecutor (); context.setTargetHost ((új HttpHost ("www.baeldung.com", 80))); HttpGet get = new HttpGet ("// www.baeldung.com"); exeRequest.execute (get, conn, context); basicConnManager.releaseConnection (csatlakozás, null, 1, TimeUnit.SECONDS); // magas szintű CloseableHttpClient kliens = HttpClients.custom () .setConnectionManager (basicConnManager) .build (); client.execute (get);

Vessünk egy pillantást a történésekre.

Először - vegye észre, hogy először alacsony szintű kapcsolatot használunk, csak azért, hogy teljes ellenőrzésünk legyen a kapcsolat felszabadulásakor, majd egy normál magasabb szintű kapcsolatot egy HttpClient-tel. A bonyolult alacsony szintű logika itt nem nagyon releváns - az egyetlen dolog, ami érdekel, az a releaseConnection hívás. Ez felszabadítja az egyetlen elérhető kapcsolatot, és lehetővé teszi újrafelhasználását.

Ezután az ügyfél ismét sikeresen végrehajtja a GET kérést. Ha kihagyjuk a kapcsolat feloldását, akkor egy IllegalStateExceptiont kapunk a HttpClient-től:

java.lang.IllegalStateException: A kapcsolatot továbbra is lefoglalják az o.a.h.u.Asserts.check (Asserts.java:34) címen az o.a.h.i.c.BasicHttpClientConnectionManager.getConnection (BasicHttpClientConnectionManager.java:248)

Ne feledje, hogy a meglévő kapcsolat nincs lezárva, csak felszabadul, majd a második kérelem újra felhasználja.

A fenti példával ellentétben a PoolingHttpClientConnectionManager lehetővé teszi a kapcsolat újrafelhasználását átláthatóan anélkül, hogy implicit módon kellene feloldani a kapcsolatot:

6.2. PéldaPoolingHttpClientConnectionManager: A szálakkal való kapcsolatok újrafelhasználása

HttpGet get = new HttpGet ("// echo.200please.com"); PoolingHttpClientConnectionManager connManager = új PoolingHttpClientConnectionManager (); connManager.setDefaultMaxPerRoute (5); connManager.setMaxTotal (5); CloseableHttpClient kliens = HttpClients.custom () .setConnectionManager (connManager) .build (); MultiHttpClientConnThread [] szálak = új MultiHttpClientConnThread [10]; for (int i = 0; i <szálak.hossz; i ++) {szálak [i] = új MultiHttpClientConnThread (kliens, get, connManager); } a (MultiHttpClientConnThread szál: szálak) {thread.start (); } a (MultiHttpClientConnThread szál: szálak) {thread.join (1000); }

A fenti példa 10 szálat tartalmaz, 10 kérést hajt végre, de csak 5 kapcsolatot oszt meg.

Természetesen ez a példa a szerverre támaszkodik Életben tartani időtúllépés. Annak érdekében, hogy az újbóli felhasználás előtt a kapcsolatok ne haljanak meg, javasoljuk a ügyfél val,-vel Életben tartani stratégiát (lásd az 5.1. példát).

7. Időkorlátok konfigurálása - Socket időtúllépés a Connection Manager használatával

Az egyetlen időtúllépés, amelyet a kapcsolatkezelő konfigurálásakor lehet beállítani, a socket időtúllépése:

7.1. Példa A Socket Timeout beállítása 5 másodpercre

HttpRoute útvonal = new HttpRoute (új HttpHost ("www.baeldung.com", 80)); PoolingHttpClientConnectionManager connManager = új PoolingHttpClientConnectionManager (); connManager.setSocketConfig (route.getTargetHost (), SocketConfig.custom (). setSoTimeout (5000) .build ());

Az időkorlátok mélyebb megvitatásához a HttpClient-en - lásd ezt.

8. Csatlakozás kilakoltatása

A kapcsolat kilakoltatása megszokta tétlen és lejárt kapcsolatok észlelése és bezárása; ennek két lehetősége van.

  1. Támaszkodva a HttpClient a kérelem végrehajtása előtt ellenőrizze, hogy a kapcsolat elavult-e. Ez egy drága lehetőség, amely nem mindig megbízható.
  2. Hozzon létre egy monitor szálat a tétlen és / vagy zárt kapcsolatok bezárásához.

8.1. Példa A HttpClient hogy ellenőrizze az elavult kapcsolatokat

PoolingHttpClientConnectionManager connManager = új PoolingHttpClientConnectionManager (); CloseableHttpClient ügyfél = HttpClients.custom (). SetDefaultRequestConfig (RequestConfig.custom (). SetStaleConnectionCheckEnabled (true) .build ()) .setConnectionManager (connManager) .build ();

8.2. Példa Elavult kapcsolatfigyelő szál használata

PoolingHttpClientConnectionManager connManager = új PoolingHttpClientConnectionManager (); CloseableHttpClient kliens = HttpClients.custom () .setConnectionManager (connManager) .build (); IdleConnectionMonitorThread staleMonitor = new IdleConnectionMonitorThread (connManager); staleMonitor.start (); staleMonitor.join (1000);

A IdleConnectionMonitorThreadosztály az alábbiakban szerepel:

public class IdleConnectionMonitorThread kiterjeszti a Threadot {private final HttpClientConnectionManager connMgr; privát volatilis logikai leállítás; public IdleConnectionMonitorThread (PoolingHttpClientConnectionManager connMgr) {super (); this.connMgr = connMgr; } @Orride public void run () {try {while (! Shutdown) {synchronized (this) {wait (1000); connMgr.closeExpiredConnections (); connMgr.closeIdleConnections (30, TimeUnit.SECONDS); }}} catch (InterruptedException ex) {shutdown (); }} public void shutdown () {shutdown = true; szinkronizált (ez) {noticeAll (); }}}

9. Csatlakozás lezárása

A kapcsolat kecsesen lezárható (a kimeneti puffert a becsukás előtt le kell öblíteni), vagy erőteljesen, a Leállitás módszer (a kimeneti puffert nem öblítik le).

A kapcsolatok megfelelő lezárásához a következőket kell elvégeznünk:

  • fogyasztani és bezárni a választ (ha zárható)
  • zárja be az ügyfelet
  • zárja be és állítsa le a kapcsolatkezelőt

8.1. Példa Kapcsolat bezárása és erőforrások felszabadítása

connManager = new PoolingHttpClientConnectionManager (); CloseableHttpClient kliens = HttpClients.custom () .setConnectionManager (connManager) .build (); HttpGet get = new HttpGet ("// google.com"); CloseableHttpResponse response = client.execute (get); EntityUtils.consume (response.getEntity ()); válasz.zár (); client.close (); connManager.close (); 

Ha a menedzsert úgy állítják le, hogy a kapcsolatok már nincsenek lezárva - az összes kapcsolat lezárul és az összes erőforrás felszabadul.

Fontos szem előtt tartani, hogy ezzel nem törlődnek azok az adatok, amelyek a meglévő kapcsolatoknál esetleg folyamatban voltak.

10. Következtetés

Ebben a cikkben megvitattuk, hogyan lehet kezelni a HttpClient HTTP Connection Management API-ját a kapcsolatok kezelésének teljes folyamata - a kinyitástól és a kiosztástól kezdve a több ügynök egyidejű használatának kezeléséig, a végleges bezárásig.

Láttuk, hogy a BasicHttpClientConnectionManager egy egyszerű megoldás az egyes kapcsolatok kezelésére, és arra, hogyan tudja kezelni az alacsony szintű kapcsolatokat. Azt is láttuk, hogy a PoolingHttpClientConnectionManager kombinálva a HttpClient Az API biztosítja a HTTP-kapcsolatok hatékony és protokollnak megfelelő használatát.


$config[zx-auto] not found$config[zx-overlay] not found