我正在使用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
Somethin與問題無關,但在ChannelPipeline的末尾添加ExecutionHandler並不會帶來任何進步。 ExecutionHandler只能用於ChannelPipeline中後面的ChannelHandler – 2012-03-23 15:56:09
如何將HttpContentEncoder添加到ChannelPipeline?我在你的代碼中看不到它?你有沒有機會分享一個實例? – 2012-03-23 15:59:14
謝謝,我更新了我的pipline,以便pipeline.addLast(「handler」,new FileUploadHandler());在executionHandler之後。至於HttpContentEncoder,我沒有在我的代碼中使用任何地方,我需要嗎?我認爲響應編碼是由HttpResponseEncoder()處理的。 – Hoofamon 2012-03-23 17:20:05