如何捕获netty中的所有异常
How to catch all exception in netty
据我所知,netty 通过覆盖方法 exceptionCaught() 来处理异常。但是我想要的是一个Handler,可以处理所有in or out的异常。所以,管道应该是这样的:
InboundExceptionHandler - inboundHandler1 - inboundHandler2 - outboundHandler1 - outboundHandler2 - OutboundExceptionHandler
这意味着我应该在我的管道中放置 2 个异常处理程序,并将其分开。但是我觉得它很难看。有更好的主意吗?
您可以在管道的 top/tail 处只有一个入站和出站异常处理程序。如果你想捕获所有异常,你可以这样做(我假设这是 Netty 4.0):
import io.netty.channel.*;
import java.net.SocketAddress;
public class ExceptionHandler extends ChannelDuplexHandler {
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
// Uncaught exceptions from inbound handlers will propagate up to this handler
}
@Override
public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
ctx.connect(remoteAddress, localAddress, promise.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
if (!future.isSuccess()) {
// Handle connect exception here...
Throwable failureCause = future.cause();
}
}
}));
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
ctx.write(msg, promise.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
if (!future.isSuccess()) {
// Handle write exception here...
Throwable failureCause = future.cause();
}
}
}));
}
// ... override more outbound methods to handle their exceptions as well
}
入站处理程序抛出的任何异常都将“向上”传播管道并调用此处理程序的 exceptionCaught()
方法,假设下面的处理程序不使用它们。
对于像write()
和connect()
这样的出站操作,你需要添加一个ChannelFutureListener
来捕获它们的异常。 exceptionCaught()
方法仅针对入站事件的异常调用,如 channelRead()
、channelActive()
等
通过管道“顶部”的这个处理程序,我们可以从下面的所有出站处理程序中捕获异常。假设您的一个出站处理程序正在执行一些编码并且失败并出现异常,这将由我们添加到 write()
操作承诺的频道未来侦听器处理。
如果这个异常处理程序像您最初建议的那样安装在管道的“底部”/头部,那么它将看不到来自其上方处理程序的异常,因为它的 write()
方法将永远不会被调用,如果先前处理程序中的写入失败。这就是此处理程序必须位于顶部的原因。
为了避免对管道的 top/bottom 产生混淆,下面是我将如何配置您的示例管道:
pipeline.addLast(outboundHandler2) // bottom
.addLast(outboundHandler1)
.addLast(inboundHandler2)
.addLast(inboundHandler1)
.addLast(new ExceptionHandler()); // top
最终的解决方案是自定义ChannelInitializer 你甚至可以添加更多的逻辑
据我所知,netty 通过覆盖方法 exceptionCaught() 来处理异常。但是我想要的是一个Handler,可以处理所有in or out的异常。所以,管道应该是这样的:
InboundExceptionHandler - inboundHandler1 - inboundHandler2 - outboundHandler1 - outboundHandler2 - OutboundExceptionHandler
这意味着我应该在我的管道中放置 2 个异常处理程序,并将其分开。但是我觉得它很难看。有更好的主意吗?
您可以在管道的 top/tail 处只有一个入站和出站异常处理程序。如果你想捕获所有异常,你可以这样做(我假设这是 Netty 4.0):
import io.netty.channel.*;
import java.net.SocketAddress;
public class ExceptionHandler extends ChannelDuplexHandler {
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
// Uncaught exceptions from inbound handlers will propagate up to this handler
}
@Override
public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
ctx.connect(remoteAddress, localAddress, promise.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
if (!future.isSuccess()) {
// Handle connect exception here...
Throwable failureCause = future.cause();
}
}
}));
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
ctx.write(msg, promise.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
if (!future.isSuccess()) {
// Handle write exception here...
Throwable failureCause = future.cause();
}
}
}));
}
// ... override more outbound methods to handle their exceptions as well
}
入站处理程序抛出的任何异常都将“向上”传播管道并调用此处理程序的 exceptionCaught()
方法,假设下面的处理程序不使用它们。
对于像write()
和connect()
这样的出站操作,你需要添加一个ChannelFutureListener
来捕获它们的异常。 exceptionCaught()
方法仅针对入站事件的异常调用,如 channelRead()
、channelActive()
等
通过管道“顶部”的这个处理程序,我们可以从下面的所有出站处理程序中捕获异常。假设您的一个出站处理程序正在执行一些编码并且失败并出现异常,这将由我们添加到 write()
操作承诺的频道未来侦听器处理。
如果这个异常处理程序像您最初建议的那样安装在管道的“底部”/头部,那么它将看不到来自其上方处理程序的异常,因为它的 write()
方法将永远不会被调用,如果先前处理程序中的写入失败。这就是此处理程序必须位于顶部的原因。
为了避免对管道的 top/bottom 产生混淆,下面是我将如何配置您的示例管道:
pipeline.addLast(outboundHandler2) // bottom
.addLast(outboundHandler1)
.addLast(inboundHandler2)
.addLast(inboundHandler1)
.addLast(new ExceptionHandler()); // top
最终的解决方案是自定义ChannelInitializer 你甚至可以添加更多的逻辑