2012-06-24 5 views
12

Beim Platzieren großer Dateien als InputStream mit dem Jersey-Client scheint der gesamte Inhalt der Datei im Speicher zwischengespeichert zu sein, bevor er an den Server gesendet wird. Dies führt zu einem Problem mit großen Dateien, da die JVM keinen Heapspeicher mehr hat. Wie verhindere ich dieses Verhalten im Jersey-Client? JAX-RS-Ressourcenmethoden auf der Serverseite scheinen dieses Problem beim Senden von Daten nicht zu haben.Verhindern, dass der Jersey-Client beim Veröffentlichen großer Dateien einen Fehler verursacht

Zum Beispiel:

WebResource dataUploadResource = buildDataUploadResource(); 
dataUploadResource.type(getMimeType()).put(getLargeInputStream()); 

Antwort

13

Um dieses Verhalten Sie den Jersey-Client konfigurieren müssen, um zu verhindern, verwendet aufgeteilte Codierung 1 für die Anforderung. Dies beseitigt die Notwendigkeit, einen Content-Length-Header zu setzen und streamt vom bereitgestellten InputStream, ohne den gesamten Inhalt im Speicher zu puffern.

Standardmäßig verwendet Jersey die HttpURLConection-Klasse des JDK, um HTTP-Anforderungen und -Antworten zu verarbeiten. Leider hat dies einige Fehler im Zusammenhang mit Chunked-Encoding-Übertragungen. Glücklicherweise verfügt Jersey über Erweiterungspunkte, um die Verwendung verschiedener HTTP-Client-Implementierungen zu ermöglichen. Eine solche Implementierung basiert auf dem Apache Http Client 2.

Zwei Implementierungen des Apache HTPP-Client-Handlers existieren, einer unterstützt die jetzt Ende des Lebens 3.x-Version, der andere verwendet die neuere 4.x-Version. Für unser Projekt haben wir eine Implementierung basierend auf der älteren (3.1) Version verwendet. Die Bibliothek ist in Maven Central unter der Untergruppe 'contribs' verfügbar.

<dependency> 
    <groupId>com.sun.jersey.contribs</groupId> 
    <artifactId>jersey-apache-client</artifactId> 
    <version>1.14</version> 
</dependency> 

Als nächstes müssen Sie Ihr Jersey-Client initialisiert die neue Implementierung zu verwenden:

Client jerseyClient = ApacheHttpClient.create(getClientConfig()); 

Um aufgeteilte Codierung zu ermöglichen, werden Sie die aufgeteilte Codierung Größe auf der Client-Konfiguration festgelegt haben als es ist nicht standardmäßig aktiviert:

private ClientConfig getClientConfig() { 
    ClientConfig config = new DefaultClientConfig(); 

    config.getProperties().put(
      DefaultApacheHttpClientConfig.PROPERTY_CHUNKED_ENCODING_SIZE, 0); 
    return config; 
} 

Solange diese Eigenschaft nicht null ist, aufgeteilte Codierung verwendet wird. In der Tat ignoriert Version 1.14 die Codierungsgröße, da die Angabe einer Größe von der zugrunde liegenden Apache Commons-httpclient-Bibliothek nicht unterstützt wird.

+1

Leider scheint dies nicht zuverlässig zu funktionieren - deshalb haben wir die codierte Codierung standardmäßig im Jersey-Code auskommentiert. Es scheint einen ekligen Fehler in HttpURLConnection zu geben, der dazu führt, dass einige Anfragen auf seltsame Weise und halb zufällig ausfallen (eine Teilmenge unserer Tests schlägt fehl, wenn wir nur die fehlgeschlagenen Tests erneut ausführen, eine kleinere Teilmenge scheitert, wenn wir sie erneut ausführen nur diese Teilmenge, selbst eine kleinere Teilmenge versagt und schließlich alle). Daher würde ich empfehlen, einen robusteren Client-Connector für ernsthafte Aufgaben zu verwenden. –

+1

Vielen Dank für Ihr Feedback. Ich habe die Antwort aktualisiert, um zu zeigen, wie der Client für die Verwendung der Chunked-Codierung mithilfe des Apache-HTTP-Clientconnectors konfiguriert wird. – Eric