2016-06-30 25 views
2

Ich baue einen einfachen Proxy-Server mit Jetty HttpClient. Ich benutze Jetty Version 9.3.10.v20160621 auf Java 1.8.0_45.Tut Jettys httpClient.setResponseBufferSize() -Methode irgendetwas?

Ich habe eine Situation, in der ich eine GET auf eine Ressource, die eine Antwort zurückgibt, die etwa 3,5 M groß ist (ich bestimmt dies mit SoapUI). Da ich weiß, dass Jettys maximale Antwortgröße standardmäßig 2M ist, mache ich Folgendes, wenn ich die HttpClient-Instanz erstelle.

 HttpClient client = new HttpClient(); 
     client.setResponseBufferSize(4194304); 
     client.start(); 

Später führe ich eine Anfrage synchron GET wie folgt:

Antwortpuffer size = 4194304

Dennoch I:

 System.out.println("response buffer size = " + client.getResponseBufferSize()); 
     retVal = client.GET(uri); 

Die Konsolenprotokoll der Folgendes bekomme ich eine java.util.concurrent.ExecutionException, wenn ich die GET() ausführen (st ack Spur unten). Ich kann nur folgern, dass entweder (a) ein Fehler in der setResponseBufferSize() -Methode vorliegt, oder (b) die Methode setResponseBufferSize() nicht das tut, was die Dokumentation sagt (die Antwortpuffergröße). Weiß jemand, was damit los ist?

java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: Buffering capacity exceeded 
    at org.eclipse.jetty.client.util.FutureResponseListener.getResult(FutureResponseListener.java:118) 
    at org.eclipse.jetty.client.util.FutureResponseListener.get(FutureResponseListener.java:101) 
    at org.eclipse.jetty.client.HttpRequest.send(HttpRequest.java:652) 
    at org.eclipse.jetty.client.HttpClient.GET(HttpClient.java:343) 
    at oracle.paas.tools.sifter.proxy.ProxySession.get(ProxySession.java:106) 
    at oracle.paas.tools.sifter.proxy.Endpoint.doGet(Endpoint.java:75) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:687) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) 
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:837) 
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:583) 
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) 
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548) 
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226) 
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180) 
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511) 
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) 
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112) 
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) 
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134) 
    at org.eclipse.jetty.server.Server.handle(Server.java:524) 
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319) 
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253) 
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273) 
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95) 
    at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93) 
    at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303) 
    at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148) 
    at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136) 
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671) 
    at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589) 
    at java.lang.Thread.run(Thread.java:745) 
Caused by: java.lang.IllegalArgumentException: Buffering capacity exceeded 
    at org.eclipse.jetty.client.util.BufferingResponseListener.onContent(BufferingResponseListener.java:114) 
    at org.eclipse.jetty.client.api.Response$Listener$Adapter.onContent(Response.java:248) 
    at org.eclipse.jetty.client.ResponseNotifier.notifyContent(ResponseNotifier.java:124) 
    at org.eclipse.jetty.client.ResponseNotifier.access$100(ResponseNotifier.java:35) 
    at org.eclipse.jetty.client.ResponseNotifier$ContentCallback.process(ResponseNotifier.java:272) 
    at org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:241) 
    at org.eclipse.jetty.util.IteratingCallback.iterate(IteratingCallback.java:224) 
    at org.eclipse.jetty.client.ResponseNotifier.notifyContent(ResponseNotifier.java:117) 
    at org.eclipse.jetty.client.HttpReceiver.responseContent(HttpReceiver.java:326) 
    at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.content(HttpReceiverOverHTTP.java:256) 
    at org.eclipse.jetty.http.HttpParser.parseContent(HttpParser.java:1584) 
    at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:1332) 
    at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.parse(HttpReceiverOverHTTP.java:158) 
    at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.process(HttpReceiverOverHTTP.java:119) 
    at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.receive(HttpReceiverOverHTTP.java:69) 
    at org.eclipse.jetty.client.http.HttpChannelOverHTTP.receive(HttpChannelOverHTTP.java:90) 
    at org.eclipse.jetty.client.http.HttpConnectionOverHTTP.onFillable(HttpConnectionOverHTTP.java:115) 
    ... 9 more 
+0

@Joakim Erdfelt danke dafür. – gilbertpilz

Antwort

2

HttpClient.setResponseBufferSize(int) ist für die interne Konfiguration der Puffergröße verwendet, um einzelne Puffer aus dem Netzwerk zu lesen.

Es hat keine Beziehung zu der Größe des Antworttextkörpers.

Die Situation, mit der Sie es zu tun haben, ist, dass der simple HttpClient.GET(uri) Aufruf die Antwort in eine FutureResponseListener Puffer aufpuffern wird, die auf 2MB Speicherauslastung beschränkt ist.

Diese Grenze ist nur ein Nebeneffekt der Java-Konzepte Future.

Dies ist eine Kurz-/Komfortmethode, die für kleine Antworten gedacht ist.

Sie haben eine Antwort, die größer ist, so dass Sie die asynchronen Features von HttpClient verwenden, um aus den Response Content Buffern/Streams, die HttpClient verwaltet, zu lesen und die Daten entsprechend Ihren Anforderungen zu verarbeiten.

Beispiel:

// In Initialization Code, start the client 
    HttpClient client = new HttpClient(); 
    client.start(); 

    // In code much later one, use the client 
    // Don't constantly start/stop the HttpClient 
    // Treat the HttpClient as a browser, and each newRequest() as 
    // a tab on that browser. 
    InputStreamResponseListener listener = new InputStreamResponseListener(); 
    // Send asynchronously with the InputStreamResponseListener 
    client.newRequest(uri).send(listener); 

    // Call to the listener's get() blocks until the headers arrived 
    Response response = listener.get(5, TimeUnit.SECONDS); 

    // Now check the response information that arrived to decide whether to read the content 
    if (response.getStatus() == 200) 
    { 
     byte[] buffer = new byte[256]; 
     try (InputStream input = listener.getInputStream()) 
     { 
      while (true) 
      { 
       int read = input.read(buffer); 
       if (read < 0) 
        break; 
       // Do something with the bytes just read 
      } 
     } 
    } 
    else 
    { 
     response.abort(new Exception()); 
    } 

Überprüfen der Httpclient Usage.java für weitere Beispiele aus

0

fand ich eine andere Art und Weise mein Problem zu lösen. Diese Lösung ist nicht so allgemein wie Joakims Lösung. Wenn die Antwort größer als 4 MiB (oder was auch immer Sie angeben) wird es die gleiche Ausnahme bekommen. Auf der anderen Seite ist es weniger Code.

Request request = client.newRequest(uri); 
FutureResponseListener listener = new FutureResponseListener(request, 4 * 1024 * 1024); 
request.send(listener); 
retVal = listener.get(); 
+0

Das wird 4 MB für jede Anfrage zuweisen, unabhängig davon, ob die Antwort tatsächlich diese Größe ist oder nicht. –

+0

Ich weiß. Wie gesagt, Ihre Lösung ist viel sauberer und allgemeiner. Das hat mich über dieses Problem hinaus geführt, also kann ich eins verschieben. – gilbertpilz