2012-03-23 33 views
0

我正在使用Netty服務器,我遇到了一個自定義處理程序問題,我通過HTTP PUT請求接收文件上傳。當我一次發送幾個文件時,一切似乎都正常,但是在大約300次連接之後,服務器似乎「中斷」了。然後,服務器將針對每個接收到的請求拋出異常。在此之後開始發生時,服務器將不再處理請求,並需要重新啓動:Netty,HTTP PUT請求的自定義處理程序問題「無法發送比請求更多的響應」

java.lang.IllegalStateException: cannot send more responses than requests 
     at org.jboss.netty.handler.codec.http.HttpContentEncoder.writeRequested(HttpContentEncoder.java:104) 
     at org.jboss.netty.handler.execution.ExecutionHandler.handleDownstream(ExecutionHandler.java:165) 
     at org.jboss.netty.channel.Channels.write(Channels.java:605) 
     at org.jboss.netty.channel.Channels.write(Channels.java:572) 
.... 

這裏是我的處理程序源channelRecieved,所有我管被分塊的要求,所以我會包括以下這些方法:

@Override 
public void messageReceived(ChannelHandlerContext context, MessageEvent event) throws Exception { 
    try { 
     log.trace("Message recieved"); 
     if (newMessage) { 
      log.trace("New message"); 
      HttpRequest request = (HttpRequest) event.getMessage(); 
      setDestinationFile(context, request); 
      newMessage = false; 
      if (request.isChunked()) { 
       log.trace("Chunked request, set readingChunks true and create byte buffer"); 
       requestContentStream = new ByteArrayOutputStream(); 
       readingChunks = true; 
       return; 
      } else { 
       log.trace("Request not chunked"); 
       writeNonChunkedFile(request); 
       requestComplete(event); 
       return; 
      } 
     } else if (readingChunks){ 
      log.trace("Reading chunks"); 
      HttpChunk chunk = (HttpChunk) event.getMessage(); 
      if (chunk.isLast()) { 
       log.trace("Read last chunk"); 
       readingChunks = false; 
       writeChunkedFile(); 
       requestComplete(event); 
       return; 
      } else { 
       log.trace("Buffering chunk content to byte buffer"); 
       requestContentStream.write(chunk.getContent().array()); 
       return; 
      } 
      // should not happen 
     } else { 
      log.error("Error handling of MessageEvent, expecting a new message or a chunk from a previous message"); 
     } 
    } catch (Exception ex) { 
     log.error("Exception: [" + ex + "]"); 
     sendError(context, INTERNAL_SERVER_ERROR); 
    } 
} 

這是我正在寫的分塊請求:

private void writeChunkedFile() throws IOException { 
    log.trace("Writing chunked file"); 
    byte[] data = requestContentStream.toByteArray(); 
    FileOutputStream fos = new FileOutputStream(destinationFile); 
    fos.write(data); 
    fos.close(); 
    log.debug("File upload complete, [chunked], path: [" + destinationFile.getAbsolutePath() + "] size: [" + destinationFile.length() + "] bytes"); 
} 

這是我如何發送響應並關閉連接:

private void requestComplete(MessageEvent event) { 
    log.trace("Request complete"); 
    HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK); 
    Channel channel = event.getChannel(); 
    ChannelFuture cf = channel.write(response); 
    cf.addListener(ChannelFutureListener.CLOSE); 
} 

我在requestComplete中嘗試了一些東西,其中一個只是channel.close(),它似乎沒有幫助。任何其他的想法或想法?

這裏是我的管道:

@Override 
public ChannelPipeline getPipeline() throws Exception { 
    final ChannelPipeline pipeline = pipeline(); 
    pipeline.addLast("decoder", new HttpRequestDecoder()); 
    pipeline.addLast("encoder", new HttpResponseEncoder()); 
    pipeline.addLast("deflater", new HttpContentCompressor()); 
    pipeline.addLast("ExecutionHandler", executionHandler); 

pipeline.addLast( 「處理程序」,新FileUploadHandler()); 返回管道; }

感謝您的任何想法或意見

編輯:管道平減指數和處理器之間登錄時的示例日誌條目:

2012-03-23T07:46:40.993 [New I/O server worker #1-6] WARN NbEvents [c.c.c.r.d.l.s.h.SbApiMessageLogger.writeRequested] [] - Sending [DefaultHttpResponse(chunked: false) 
HTTP/1.1 100 Continue] 
2012-03-23T07:46:40.995 [New I/O server worker #1-6] WARN NbEvents [c.c.c.r.d.l.s.h.SbApiMessageLogger.writeRequested] [] - Sending [DefaultHttpResponse(chunked: false) 
HTTP/1.1 500 Internal Server Error 
Content-Type: text/plain; charset=UTF-8] 
2012-03-23T07:46:41.000 [New I/O server worker #1-7] DEBUG NbEvents [c.c.c.r.d.l.s.h.SbApiMessageLogger.messageReceived] [] - Received [PUT /a/deeper/path/testFile.txt HTTP/1.1 
User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.12.9.0 zlib/1.2.3 libidn/1.18 libssh2/1.2.2 
Host: 192.168.0.1:8080 
Accept: */* 
Content-Length: 256000 
Expect: 100-continue 
+0

Somethin與問題無關,但在ChannelPipeline的末尾添加ExecutionHandler並不會帶來任何進步。 ExecutionHandler只能用於ChannelPipeline中後面的ChannelHandler – 2012-03-23 15:56:09

+0

如何將HttpContentEncoder添加到ChannelPipeline?我在你的代碼中看不到它?你有沒有機會分享一個實例? – 2012-03-23 15:59:14

+0

謝謝,我更新了我的pipline,以便pipeline.addLast(「handler」,new FileUploadHandler());在executionHandler之後。至於HttpContentEncoder,我沒有在我的代碼中使用任何地方,我需要嗎?我認爲響應編碼是由HttpResponseEncoder()處理的。 – Hoofamon 2012-03-23 17:20:05

回答

0

這結束了我的執行出了問題,不涉及任何在這裏發佈的代碼,這裏發佈的邏輯看起來很合理,並且工作正常。這就是說,非常感謝所有有用的評論!

+3

如果其他人看到相同的錯誤,可以發佈有關您發現的問題以及您的實現的信息,這會有所幫助。 – 2013-06-17 19:39:22