2012-03-23 1 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()); обратный трубопровод; }

Спасибо за любые мысли или идеи

Edit: въездной образца журнала при входе между дефлятором и обработчиком в трубопроводе:

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

Что-то не связано с проблемой, но добавление ExectionHandler в конце ChannelPipeline не дает вам никаких успехов. ExecutionHandler будет работать только для ChannelHandlers, которые находятся за ним в ChannelPipeline. –

+0

Как вы добавляете HttpContentEncoder в ChannelPipeline? Я не вижу этого в вашем коде? Вы можете поделиться случаем случайно? –

+0

Спасибо, я обновил мою трубопровод так, чтобы pip.addLast («обработчик», новый FileUploadHandler()); приходит после исполненияHandler. Что касается HttpContentEncoder, я не использую это где-либо в своем коде, мне нужно быть? Я думал, что кодировка ответа обрабатывается HttpResponseEncoder(). – Hoofamon

ответ

0

Это закончилось тем, что проблема с моей реализацией, не связанные с любой из кода, размещенного здесь, логика, размещенная здесь, кажется звуковой и работает нормально. Тем не менее, большое спасибо всем за полезные комментарии!

+3

Было бы полезно, чтобы другие видели ту же ошибку, чтобы опубликовать что-то о том, какую проблему вы обнаружили с вашей реализацией. –

 Смежные вопросы

  • Нет связанных вопросов^_^