2016-06-30 44 views
2

我正在使用Jetty的HttpClient構建一個簡單的代理服務器。我在Java 1.8.0_45上使用Jetty版本9.3.10.v20160621。Jetty的httpClient.setResponseBufferSize()方法能做什麼嗎?

我有一種情況,我在一個資源上做了一個GET,它將返回一個大約3.5M的響應(我使用soapUI確定了這個)。知道Jetty的默認最大響應大小是2M,我在創建HttpClient實例時執行以下操作。

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

後來我執行同步GET請求,像這樣:

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

控制檯日誌具有以下:

響應緩衝器大小= 4194304

然而,我當我執行GET()(st。)時得到java.util.concurrent.ExecutionException ack跟蹤)。我只能得出結論:(a)setResponseBufferSize()方法中存在錯誤,或者(b)setResponseBufferSize()方法不執行文檔所說的操作(設置響應緩衝區大小)。有人知道這是什麼嗎?

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謝謝你。 – gilbertpilz

回答

2

HttpClient.setResponseBufferSize(int)是用於配置用於從網絡上讀取各個緩衝器內部緩衝器的大小。

它與您的Response主體內容大小沒有任何關係。

您正在處理的情況是,簡單的HttpClient.GET(uri)調用會將響應緩衝到FutureResponseListener,該限制爲2MB的內存使用量。

此限制僅僅是java Future概念的副作用。

這是一個速記/方便的方法,用於小回復。

您有更大的響應,所以它對您使用HttpClient的異步功能從HttpClient管理的響應內容緩衝區/流讀取,根據您需要執行的操作處理數據。

例子:

// 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()); 
    } 

退房HttpClient的Usage.java更多的例子

0

我找到解決我的問題的另一種方式。這個解決方案不像Joakim的解決方案一般。如果響應大於4 MiB(或您指定的任何內容),它將得到相同的異常。另一方面,它的代碼更少。

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

這將爲每個請求分配4MB,而不管響應是否實際爲該大小。 –

+0

我知道。正如我所說,你的解決方案更清潔,更通用。這只是讓我過去的問題,所以我可以移動一個。 – gilbertpilz

相關問題