Java 如何使用Netty编写一个异步HttpServer
我正在尝试创建一个简单的异步Netty HTTP服务器。我需要支持的关键特性是能够将封装在事件中的HttpRequest发送到事件驱动组件(在同一JVM中),该组件将处理事件并生成响应。此事件驱动组件在Netty组件的单独线程中运行 我遵循了许多示例来构建一些应该适合我的东西,并且当响应与处理程序在同一个线程中生成时,我所拥有的东西也可以工作 我编写/改编的自定义处理程序是:Java 如何使用Netty编写一个异步HttpServer,java,netty,Java,Netty,我正在尝试创建一个简单的异步Netty HTTP服务器。我需要支持的关键特性是能够将封装在事件中的HttpRequest发送到事件驱动组件(在同一JVM中),该组件将处理事件并生成响应。此事件驱动组件在Netty组件的单独线程中运行 我遵循了许多示例来构建一些应该适合我的东西,并且当响应与处理程序在同一个线程中生成时,我所拥有的东西也可以工作 我编写/改编的自定义处理程序是: private class WebServerHandler extends SimpleChannelInbo
private class WebServerHandler extends SimpleChannelInboundHandler<Object> {
String uri;
@Override
public void messageReceived(final ChannelHandlerContext ctx, final Object msg) {
if (!(msg instanceof FullHttpRequest)) return;
final FullHttpRequest request = (FullHttpRequest) msg;
uri = request.uri();
System.out.println("Handling: " + uri);
if (HttpUtil.is100ContinueExpected(request)) send100Continue(ctx);
final Handler handler = WebServer.this.getHandler(request.uri());
if (handler == null) {
writeNotFound(ctx, request);
} else {
try {
handler.handle(ctx, request);
} catch (final Throwable ex) {
ex.printStackTrace();
writeInternalServerError(ctx, request);
}
}
}
@Override
public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) {
ctx.close();
}
@Override
public void channelReadComplete(final ChannelHandlerContext ctx) {
System.out.println("Completed: " + uri);
// ctx.flush();
}
}
我没有包含事件驱动组件的任何信息,因为它是一个大型而复杂的系统(实际上是一种编程语言),但我知道相关代码正在成功调用。我试图执行以生成响应的实际代码是:
File file = new File(file_uri);
System.out.println("file: " + file.getAbsolutePath());
RandomAccessFile raf = new RandomAccessFile(file, "r");
HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
HttpUtil.setContentLength(response, raf.length());
ctx.write(response);
ctx.write(new DefaultFileRegion(raf.getChannel(), 0, file.length()));
ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
raf.close();
所以,我的问题是-在我发送响应之前,如何阻止Netty调用
channelReadComplete(…)
方法?我认为您的raf.close
调用应该在附加到文件写入的侦听器中。如前所述,我希望您在write调用有机会读取所有文件之前关闭该文件。您的响应正确地设置了内容长度,但是如果您没有写入那么多字节,因为您提前关闭了文件,那么您的客户端将挂起等待其余的字节
您应该在管道中的聚合器之前移动编码器。聚合器可以发送编码器需要编码的响应。考虑使用,因为它可以用一个处理程序替换编码器/解码器
您可以使用对象作为类型扩展SimpleChannelInboundHandler,但随后拒绝FullHttpRequest消息之外的任何消息。如果您更改扩展中的类型,那么(您是否使用Netty 5?为什么?)
例如:
... extends SimpleChannelInboundHandler<FullHttpRequest> {
...
public void messageReceived(ChannelHandlerContext ctx, FullHttpRequest request) {
。。。扩展SimpleChannelInboundHandler{
...
收到公共无效消息(ChannelHandlerContext ctx,FullHttpRequest请求){
我不认为早期调用
channelReadComplete
对您的场景很重要。因为您已经在读取/响应处理程序中刷新了channelReadComplete
。非常感谢您-raf.close()的放置在一个听众中修复了我的问题。谢谢你的其他欢迎推荐!
... extends SimpleChannelInboundHandler<FullHttpRequest> {
...
public void messageReceived(ChannelHandlerContext ctx, FullHttpRequest request) {