0

Ich schreibe eine Singleton-Klasse (Object in scala), die Apache httpclient (4.5.2) verwendet, um einige Dateiinhalte zu posten und den Status an den Aufrufer zurückzugeben.scala: apache httpclient in multi-threaded Umgebung

object HttpUtils{ 
    protected val retryHandler = new HttpRequestRetryHandler() { 
    def retryRequest(exception: IOException, executionCount: Int, context: HttpContext): Boolean = { 
     //retry logic 
     true 
    } 
    } 
    private val connectionManager = new PoolingHttpClientConnectionManager() 

    // Reusing same client for each request that might be coming from different threads . 
    // Is it correct ???? 
    val httpClient = HttpClients.custom() 
    .setConnectionManager(connectionManager) 
    .setRetryHandler(retryHandler) 
    .build() 

    def restApiCall (url : String, rDD: RDD[SomeMessage]) : Boolean = { 
    // Creating new context for each request 
    val httpContext: HttpClientContext = HttpClientContext.create 
    val post = new HttpPost(url) 

    // convert RDD to text file using rDD.collect 

    // add this file as MultipartEntity to post 

    var response = None: Option[CloseableHttpResponse] // Is it correct way of using it ? 
    try { 
     response = Some(httpClient.execute(post, httpContext)) 
     val responseCode = response.get.getStatusLine.getStatusCode 
     EntityUtils.consume(response.get.getEntity) // Is it require ??? 
     if (responseCode == 200) true 
     else false 
    } 
    finally { 
     if (response.isDefined) response.get.close 
     post.releaseConnection() // Is it require ??? 
    } 
    } 
    def onShutDown = { 
    connectionManager.close() 
    httpClient.close() 
    } 
} 

Mehrere Threads (Spezifischer von Funken Streaming Kontext) fordern restApiCall Methode. Ich bin relativ neu zu scala und apache httpClient. Ich muss häufige Verbindungen zu nur wenigen festen Servern herstellen (d. H. 5-6 feste URLs mit verschiedenen Anfrageparametern).

Ich ging durch mehrere Online-Ressource, aber immer noch nicht zuversichtlich darüber.

  • Ist es der beste Weg, HTTP-Client in Multi-Thread-Umgebung zu verwenden?
  • Ist es möglich, Live-Verbindungen zu behalten und sie für verschiedene Anfragen zu verwenden? Wird es in diesem Fall von Vorteil sein?
  • Nutze/gebe ich alle Ressourcen effizient frei? Wenn nicht, bitte vorschlagen.
  • Ist es gut, es in Scala zu verwenden oder gibt es eine bessere Bibliothek?

Vielen Dank im Voraus.

+0

Ich würde Ihnen empfehlen, 'https: // github.com/scalaj/scalaj-http' zu verwenden. Sie haben eine ausdrückliche Garantie, dass die API Thread-sicher ist. Es sieht so aus, als ob der Apache HTTPClient bestimmte Multithreading-Überlegungen benötigt. http://hc.apache.org/httpclient-3.x/threading.html – maasg

+0

Ich benutze Client-Version 4.5.2. Der Link beschreibt 3.x –

Antwort

0

Es scheint, die official docs haben Antworten auf alle Ihre Fragen:

2.3.3. Verbindungsmanager Pooling

PoolingHttpClientConnectionManager ist eine komplexere Implementierung , die einen Pool von Client-Verbindungen verwaltet und ist in der Lage Verbindungsanforderungen von mehreren Ausführungs-Threads zu bedienen. Die Verbindungen sind , die pro Strecke zusammengefasst werden. Eine Anfrage für eine Route, für die der Manager bereits eine persistente Verbindung im Pool verfügbar hat, wird bedient, indem eine Verbindung vom Pool gemietet wird, anstatt eine brandneue Verbindung zu erstellen.

PoolingHttpClientConnectionManager verwaltet eine Höchstgrenze von Verbindungen pro Strecke und insgesamt. Standardmäßig erstellt diese Implementierung nicht mehr als 2 gleichzeitige Verbindungen pro angegebene Route und nicht mehr als 20 Verbindungen insgesamt. Für viele reale Anwendungen können sich diese Beschränkungen als zu einschränkend erweisen, insbesondere wenn sie HTTP als Transportprotokoll für ihre Dienste verwenden.


2,4. Multithreaded-Anforderungs-Ausführungs

Wenn es mit einem Verbindungsmanager-Pooling ausgestattet wie PoolingClientConnectionManager kann Httpclient verwendet werden mehrere Anforderungen gleichzeitig mit mehreren Ausführungs-Threads auszuführen.

Der PoolingClientConnectionManager weist Verbindungen basierend auf seiner Konfiguration zu. Wenn alle Verbindungen für eine bestimmte Route bereits geleast wurden, wird eine Verbindungsanforderung blockiert, bis eine Verbindung zurück in den Pool freigegeben wird.Man kann sicherstellen, dass der Verbindungsmanager nicht unbegrenzt in der Verbindungsanfrageoperation durch blockiert, die 'http.conn-manager.timeout' auf einen positiven Wert setzt. Wenn die Verbindungsanforderung nicht innerhalb des angegebenen Zeitraums bearbeitet werden kann, wird ConnectionPoolTimeoutException ausgelöst.

+0

Ich habe diese Dokumentation gelesen, aber das hat kein detailliertes Beispiel/Erklärung der Ressourcenfreigabe. Ich habe auch Apis Dokumentation durchgesehen, aber nichts nützliches bekommen. –

Verwandte Themen