2012-06-24 11 views
12

Kiedy positing dużych plików jako InputStream używającej klienta Jersey, wydaje się, że cała zawartość pliku jest buforowane w pamięci przed wysłaniem do serwera. Powoduje to problem z dużymi plikami, gdy JVM kończy się przestrzeń sterty. Jak zapobiec tego zachowania w kliencie Jersey? Metody zasobów JAX-RS po stronie serwera nie wydają się mieć tego problemu podczas wysyłania danych.Zapobieganie klienta Jersey od powodując OutOfMemory błąd podczas wysyłania dużych plików

Na przykład:

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

Odpowiedz

13

W celu uniknięcia tego problemu trzeba skonfigurować klienta Jersey używać pofragmentowane kodowanie 1 na żądanie. Eliminuje to konieczność ustawiania nagłówka Content-Length i będzie przesyłane strumieniowo z dostarczonego strumienia InputStream bez buforowania całej zawartości w pamięci.

Domyślnie Jersey używa klasy HttpURLConection JDK do obsługi żądań HTTP i odpowiedzi. Niestety ma to kilka błędów związanych z przesyłaniem kodowania kodowanego. Na szczęście firma Jersey ma punkty rozszerzenia, aby umożliwić korzystanie z różnych implementacji klienta HTTP. Jedna taka implementacja jest oparta na kliencie HTTP Apache 2.

Istnieją dwie implementacje obsługi klienta apache htpp, jedna obsługuje wersję 3.X, druga używa nowszej wersji 4.x. Do naszego projektu wykorzystaliśmy implementację opartą na starszej wersji (3.1). Biblioteka jest dostępna w Maven Central w podgrupie "contribs".

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

Następnie trzeba zainicjować klienta Jersey do korzystania z nowego realizacji:

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

W celu umożliwienia pofragmentowane kodowanie, musisz ustawić format kodowania pakietowego od konfiguracji klienta jako to nie jest domyślnie włączona:

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

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

dopóki ta właściwość nie jest null, pofragmentowane kodowanie zostaną wykorzystane. W rzeczywistości wersja 1.14 ignoruje rozmiar kodowania, ponieważ określanie rozmiaru nie jest obsługiwane przez bazową bibliotekę commons-httpclient.

+1

Niestety, wygląda na to, że nie działa to niezawodnie - dlatego domyślnie kodowanie zostało ukryte w kodzie Jersey. Wygląda na to, że w HttpURLConnection występuje nieprzyjemny błąd, który powoduje, że niektóre żądania kończą się niepowodzeniem w sposób dziwny i pół-losowy (podzbiór naszych testów się nie powiódł, jeśli ponownie wykonamy tylko testy zakończone niepowodzeniem, mniejszy ich zestaw nie powiedzie się, jeśli ponownie uruchomimy tylko ten podzbiór, nawet mniejszy podzbiór kończy się niepowodzeniem i ostatecznie wszystkie przechodzą). Zalecam więc użycie solidniejszego konektora klienta do każdej poważnej pracy. –

+1

Dziękujemy za opinię. Zaktualizowałem odpowiedź, aby pokazać, jak skonfigurować klienta do korzystania z kodowania fragmentarycznego za pomocą złącza klienta Apache Http. – Eric

Powiązane problemy