Netty异常传播机制

java 复制代码
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
        throws Exception {
    ctx.fireExceptionCaught(cause);
}

调用ctx.fireExceptionCaught(cause); 来进行异常的向下传播,ctx是ChannelHandlerContext。因为pipeline中的每个节点是以ChannelHandlerContext形式构成的双向链表。

AbstractChannelHandlerContext 是顶级抽象,每个ChannelHandlerContext内部都持有一个指针指向下一个节点和上一个节点。

java 复制代码
abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
        implements ChannelHandlerContext, ResourceLeakHint {
    volatile AbstractChannelHandlerContext next;
    volatile AbstractChannelHandlerContext prev;
    }

ctx.fireExceptionCaught(cause);这个方法在把异常向下传播。这个方法显然需要定义在抽象类AbstractChannelHandlerContext中。因为每一个节点都有权利来决定是否向下传播,现在这个设计定义在父级抽象类中更合适。

父类中定义了如下代码:

java 复制代码
@Override
public ChannelHandlerContext fireExceptionCaught(final Throwable cause) {
   invokeExceptionCaught(next, cause);
   return this;
}

static void invokeExceptionCaught(final AbstractChannelHandlerContext next, final Throwable cause) {
   ObjectUtil.checkNotNull(cause, "cause");
   EventExecutor executor = next.executor();
   if (executor.inEventLoop()) {
       next.invokeExceptionCaught(cause);
   } else {
       try {
           executor.execute(new Runnable() {
               @Override
               public void run() {
                   next.invokeExceptionCaught(cause);
               }
           });
       } catch (Throwable t) {
           if (logger.isWarnEnabled()) {
               logger.warn("Failed to submit an exceptionCaught() event.", t);
               logger.warn("The exceptionCaught() event that was failed to submit was:", cause);
           }
       }
   }
}

上面的代码看出,实际调用是父级的静态抽象方法:

static void invokeExceptionCaught(final AbstractChannelHandlerContext next, final Throwable cause) 这个方法接收两个参数 第一个 就是:下一个要传播的节点next, 第二个就是:传播的异常。显然next的取值来自于双向链表的下一个指针。也就是最上面的volatile AbstractChannelHandlerContext next;

最终都会调用到:每一个节点的invokeExceptionCaught

invokeExceptionCaught也是定义在抽象类中的,并且是private方法。

java 复制代码
private void invokeExceptionCaught(final Throwable cause) {
    if (invokeHandler()) {
        try {
            handler().exceptionCaught(this, cause);
        } catch (Throwable error) {
            if (logger.isDebugEnabled()) {
                logger.debug(
                    "An exception {}" +
                    "was thrown by a user handler's exceptionCaught() " +
                    "method while handling the following exception:",
                    ThrowableUtil.stackTraceToString(error), cause);
            } else if (logger.isWarnEnabled()) {
                logger.warn(
                    "An exception '{}' [enable DEBUG level for full stacktrace] " +
                    "was thrown by a user handler's exceptionCaught() " +
                    "method while handling the following exception:", error, cause);
            }
        }
    } else {
        fireExceptionCaught(cause);
    }
}

整个这个private中的逻辑 invokeHandler()是先检查是否handler被移除了,是否还有效,如果有效就调用handler的handler().exceptionCaught(this, cause)

权限收口: 将核心执行逻辑设为 private,是为了防止子类破坏"检查-执行-保护"的固定流水线流程。

抽象类处理通用的框架逻辑,不让用户自己私自修改,防止流程上被破坏,只是给用户留了handler中的exceptionCaught用来决定怎么处理异常。

异常的传播,牢牢的掌握在AbstractChannelHandlerContext这个类中。AbstractChannelHandlerContext负责整个流程的契约。防止 "子类破坏了父类的契约"

总结

1.异常从pipeline中的当前节点,一直向后传播,一直到tail节点。不区分inboundHandler还是outboundHandler

2.如果handler不重写 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception

ChannelInboundHandlerAdapter的默认实现就是直接向下传播。

java 复制代码
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
        throws Exception {
    ctx.fireExceptionCaught(cause);
}

3.整个流程都封装在抽象类中了,防止开发者破坏整个pipeline的流转流程

相关推荐
于先生吖2 小时前
基于 Java 开发智慧社区系统:跑腿 + 家政 + 本地生活服务实战教程
java·开发语言·生活
魑魅魍魉都是鬼2 小时前
JAVA面向对象设计的五大原则
java
小箌2 小时前
springboot_01
java·spring boot·后端
sunwenjian8862 小时前
Spring Cloud gateway 路由规则
java
panzer_maus2 小时前
死锁的产生与解决
java·开发语言
asom222 小时前
MVC vs DDD
java·mvc·ddd
REDcker2 小时前
Linux Core Dump 配置与分析指南
linux·运维·服务器
凯子坚持 c2 小时前
基于C++构建DeepSeek大模型推理SDK:从架构设计到工程落地
java·数据库·c++
星河耀银海2 小时前
C++ 异常处理机制:异常捕获、自定义异常与实战应用
android·java·c++