出站 ChannelHandler 的捕获所有异常处理

2024-01-11

在 Netty 中,您有入站和出站处理程序的概念。只需在管道的末尾(尾部)添加一个通道处理程序并实现一个捕获所有入站异常处理程序即可实现exceptionCaught覆盖。如果未沿途处理,沿入站管道发生的异常将沿着处理程序传播,直到遇到最后一个处理程序。

传出处理程序并没有完全相反的情况。相反(根据 Netty in Action,第 94 页),您需要向频道的 Future或听众Promise传递到write你的方法Handler.

由于我不确定在哪里插入前者,我想我会选择后者,所以我做了以下内容ChannelOutboundHandler:


    /**
     * Catch and log errors happening in the outgoing direction
     *
     * @see <p>p94 in "Netty In Action"</p>
     */
    private ChannelOutboundHandlerAdapter createOutgoingErrorHandler() {
        return new ChannelOutboundHandlerAdapter() {
            @Override
            public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
                logger.info("howdy! (never gets this far)");

                final ChannelFutureListener channelFutureListener = future -> {
                    if (!future.isSuccess()) {
                        future.cause().printStackTrace();
                        // ctx.writeAndFlush(serverErrorJSON("an error!"));
                        future.channel().writeAndFlush(serverErrorJSON("an error!"));
                        future.channel().close();
                    }
                };
                promise.addListener(channelFutureListener);
                ctx.write(msg, promise);
            }
        };

这被添加到管道的头部:

    @Override
    public void addHandlersToPipeline(final ChannelPipeline pipeline) {
        pipeline.addLast(
                createOutgoingErrorHandler(),
                new HttpLoggerHandler(), // an error in this `write` should go "up"
                authHandlerFactory.get(),
                // etc

问题是write如果我在错误处理程序中抛出运行时异常,则永远不会调用我的错误处理程序的方法HttpLoggerHandler.write().

我该如何做这个工作?任何传出处理程序中的错误都应该“冒泡”到附加到头部的错误。

需要注意的重要一点是,我不仅仅是想关闭通道,我想将错误消息写回到客户端(从serverErrorJSON('...')。在我尝试调整处理程序的顺序时(也尝试了来自这个答案 https://stackoverflow.com/q/30994095/200987),我已经激活了监听器,但我无法写任何东西。如果我用过ctx.write()在监听器中,似乎我在使用时进入了一个循环future.channel().write...没有做任何事情。


我找到了一个非常简单的解决方案,允许入站和出站异常到达与管道中最后一个 ChannelHandler 相同的异常处理程序。

我的管道设置如下:

        //Inbound propagation
        socketChannel.pipeline()
          .addLast(new Decoder())
          .addLast(new ExceptionHandler());

        //Outbound propagation
        socketChannel.pipeline()
          .addFirst(new OutboundExceptionRouter())
          .addFirst(new Encoder());

这是我的 ExceptionHandler 的内容,它记录捕获的异常:

    public class ExceptionHandler extends ChannelInboundHandlerAdapter {
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            log.error("Exception caught on channel", cause);
        }
    }

现在,OutBoundExceptionRouter 中甚至允许 ExceptionHandler 处理出站异常:

    public class OutboundExceptionRouter extends ChannelOutboundHandlerAdapter {
        @Override
        public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
            promise.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
            super.write(ctx, msg, promise);
        }
    }

这是我的管道中调用的第一个出站处理程序,它的作用是将一个侦听器添加到将执行的出站写入承诺中future.channel().pipeline().fireExceptionCaught(future.cause());当承诺落空时。这fireExceptionCaught方法通过管道向入站方向传播异常,最终到达 ExceptionHandler。


如果有人感兴趣的话,从 Netty 4.1 开始,我们需要添加一个监听器来获取异常,因为在对通道执行 writeAndFlush 后,调用Write0方法 https://github.com/netty/netty/blob/830fc0d660896ce781aba0a8eb614053a4fe9201/transport/src/main/java/io/netty/channel/AbstractChannelHandlerContext.java#L715在 AbstractChannelHandlerContext.java 中调用,它将写入操作包装在 try catch 块中。 catch 块通知 Promise 而不是调用fireExceptionCaught 就像 invokeChannelRead 方法一样 https://github.com/netty/netty/blob/830fc0d660896ce781aba0a8eb614053a4fe9201/transport/src/main/java/io/netty/channel/AbstractChannelHandlerContext.java#L376用于入站消息。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

出站 ChannelHandler 的捕获所有异常处理 的相关文章

  • Java EE:如何获取我的应用程序的 URL?

    在 Java EE 中 如何动态检索应用程序的完整 URL 例如 如果 URL 是 localhost 8080 myapplication 我想要一个可以简单地将其作为字符串或其他形式返回给我的方法 我正在运行 GlassFish 作为应
  • Play框架运行应用程序问题

    每当我尝试运行使用以下命令创建的新 Web 应用程序时 我都会收到以下错误Play http www playframework org Error occurred during initialization of VM Could no
  • 如何找到给定字符串的最长重复子串

    我是java新手 我被分配寻找字符串的最长子字符串 我在网上研究 似乎解决这个问题的好方法是实现后缀树 请告诉我如何做到这一点或者您是否有任何其他解决方案 请记住 这应该是在 Java 知识水平较低的情况下完成的 提前致谢 附 测试仪字符串
  • 未捕获 Func<> 的异常(异步)

    我有以下代码 为了进行此重现而进行了简化 显然 catch 异常块将包含更多逻辑 我有以下代码 void Main var result ExecuteAction async gt Will contain real async code
  • 多个 Maven 配置文件激活多个 Spring 配置文件

    我想在 Maven 中构建一个环境 在其中我想根据哪些 Maven 配置文件处于活动状态来累积激活多个 spring 配置文件 目前我的 pom xml 的相关部分如下所示
  • 操作错误不会显示在 JSP 上

    我尝试在 Action 类中添加操作错误并将其打印在 JSP 页面上 当发生异常时 它将进入 catch 块并在控制台中打印 插入异常时出错 请联系管理员 在 catch 块中 我添加了它addActionError 我尝试在jsp页面中打
  • 磁模拟

    假设我在 n m 像素的 2D 表面上有 p 个节点 我希望这些节点相互吸引 使得它们相距越远吸引力就越强 但是 如果两个节点之间的距离 比如 d A B 小于某个阈值 比如 k 那么它们就会开始排斥 谁能让我开始编写一些关于如何随时间更新
  • 如何在PreferenceActivity中添加工具栏

    我已经使用首选项创建了应用程序设置 但我注意到 我的 PreferenceActivity 中没有工具栏 如何将工具栏添加到我的 PreferenceActivity 中 My code 我的 pref xml
  • 十进制到八进制的转换[重复]

    这个问题在这里已经有答案了 可能的重复 十进制转换错误 https stackoverflow com questions 13142977 decimal conversion error 我正在为一个类编写一个程序 并且在计算如何将八进
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • 总是使用 Final?

    我读过 将某些东西做成最终的 然后在循环中使用它会带来更好的性能 但这对一切都有好处吗 我有很多地方没有循环 但我将 Final 添加到局部变量中 它会使速度变慢还是仍然很好 还有一些地方我有一个全局变量final 例如android Pa
  • 加密 JBoss 配置中的敏感信息

    JBoss 中的标准数据源配置要求数据库用户的用户名和密码位于 xxx ds xml 文件中 如果我将数据源定义为 c3p0 mbean 我会遇到同样的问题 是否有标准方法来加密用户和密码 保存密钥的好地方是什么 这当然也与 tomcat
  • 如何在控制器、服务和存储库模式中使用 DTO

    我正在遵循控制器 服务和存储库模式 我只是想知道 DTO 在哪里出现 控制器应该只接收 DTO 吗 我的理解是您不希望外界了解底层域模型 从领域模型到 DTO 的转换应该发生在控制器层还是服务层 在今天使用 Spring MVC 和交互式
  • 如何从指定日期获取上周五的日期? [复制]

    这个问题在这里已经有答案了 如何找出上一个 上一个 星期五 或指定日期的任何其他日期的日期 public getDateOnDay Date date String dayName 我不会给出答案 先自己尝试一下 但是 也许这些提示可以帮助
  • 在mockito中使用when进行模拟ContextLoader.getCurrentWebApplicationContext()调用。我该怎么做?

    我试图在使用 mockito 时模拟 ContextLoader getCurrentWebApplicationContext 调用 但它无法模拟 here is my source code Mock org springframewo
  • simpleframework,将空元素反序列化为空字符串而不是 null

    我使用简单框架 http simple sourceforge net http simple sourceforge net 在一个项目中满足我的序列化 反序列化需求 但在处理空 空字符串值时它不能按预期工作 好吧 至少不是我所期望的 如
  • 静态变量的线程安全

    class ABC implements Runnable private static int a private static int b public void run 我有一个如上所述的 Java 类 我有这个类的多个线程 在里面r
  • java.lang.IllegalStateException:驱动程序可执行文件的路径必须由 webdriver.chrome.driver 系统属性设置 - Similiar 不回答

    尝试学习 Selenium 我打开了类似的问题 但似乎没有任何帮助 我的代码 package seleniumPractice import org openqa selenium WebDriver import org openqa s
  • 如何实现仅当可用内存较低时才将数据交换到磁盘的写缓存

    我想将应用程序生成的数据缓存在内存中 但如果内存变得稀缺 我想将数据交换到磁盘 理想情况下 我希望虚拟机通知它需要内存并将我的数据写入磁盘并以这种方式释放一些内存 但我没有看到任何方法以通知我的方式将自己挂接到虚拟机中before an O
  • 节拍匹配算法

    我最近开始尝试创建一个移动应用程序 iOS Android 它将自动击败比赛 http en wikipedia org wiki Beatmatching http en wikipedia org wiki Beatmatching 两

随机推荐

  • 找到每组内的最大值和最小值[重复]

    这个问题在这里已经有答案了 我想在下表中找到每个基因的最大值和最小值 我知道 以下函数给出了最大值 或最小值 但我无法同时获得两者 tapply df Value df Gene max 欣赏 小测试集 df lt read table h
  • Spark fillNa 不替换 null 值

    我有以下数据集 它包含一些空值 需要使用 Spark 中的 fillna 替换空值 数据框 df spark read format com databricks spark csv option header true load sam
  • Android 模拟器以不同的分辨率启动

    有时我的 AVD 启动时的分辨率比预期的要高 我在运行它之前不会修改任何设置 此外 重新启动时 它会以正确的分辨率启动 虽然并不重要 但有时确实会浪费时间 我不确定为什么会这样 但我只是在启动之前编辑了详细信息并启用了从快照选项启动 这确实
  • 用于值类型 int 的 ASP.NET MVC 2 编辑器模板

    我想为值类型 即 int 创建一个 MVC 2 编辑器模板 有人用预览 1 位完成此操作吗 非常感谢 当您在回发时提交值时 尼克 克拉克的答案会起作用吗 在 MVC2 预览版 2 中 调用 Html Textbox abc Model To
  • Rails 控制器中的 Process.fork

    我们正在对一个新应用程序进行一些原型设计 并注意到其中一个操作需要很长时间才能加载 80 120 秒 由于很多处理不需要在页面加载时进行 我们可以稍后通过 Ajax 请求数据 我想到使用Process fork允许页面立即返回 而处理仍在
  • 如何更改 iPhone 中文本字段的背景颜色?

    我想将文本字段的背景颜色更改为透明的颜色 我努力了 option5btn backgroundColor UIColor grayColor 但我想要一些其他颜色 谁能告诉我 iPhone 文本字段的背景中可以使用哪些所有颜色 谁能帮我这个
  • 数组上的 MongoDB 地理空间索引(多键 + 地理空间)

    这是我的数据的简化版本 gt db foo insert name jim locations 10 10 3 6 1 2 gt db foo insert name john locations 1 5 2 4 我希望能够做类似的事情 g
  • 不需要公司名称 WooCommerce(第 3 方插件)

    我想让 WooCommerce 中不需要计费公司和运输公司 由于某种原因 我使用的代码适用于除公司部分之外的所有内容 事实证明 第三方插件需要公司名称 以下是该插件的完整代码
  • MongoDB 中的 UpdateMany 使用 $inc 运行两次

    感谢我在上一个问题中得到的帮助 使用文档中的值更新许多 mongodb 文档 https stackoverflow com questions 63530102 updatemany mongodb documents with valu
  • 聚合和聚合根的混淆

    我被分配了一个非常简单的项目作为考试 我有想法使用领域驱动设计来开发它 你们中的许多人可能会说该应用程序非常简单 使用存储库和 UoW 只是浪费时间 您可能是对的 但我认为这是一个学习更多东西的机会 该应用程序是一个 机票 系统 从下图中您
  • 视差部分初始背景位置与页面滚动时不一致

    我花了一整天的时间尝试创建一个视差部分 无论它放在页面上的哪个位置 它都能正常工作 但我对代码所做的每一次更改都会解决一个问题并产生另一个问题 到目前为止 这是我的代码 function use strict parallax sectio
  • 如何在 antd select 上添加分页?因为从接口获取数据是巨大的。所以我想实现分页

    如何在 Antd 的 Select 上添加分页 因为从接口获取数据是巨大的 所以我想实现分页 但文档api不支持 import Select from antd const Option Select Option let province
  • 使用地理定位和 Google 地图 API [帮助]

    我是移动开发领域的新手 现在我正在构建一个使用 jQuery mobile 和 PhoneGap 的应用程序 这是我的逻辑 我有一个包含用户及其地址的表 我获取用户地址并通过地图 API 传递它以捕获位置 但我对每条记录都这样做 有时 AP
  • Firestore Web 代码示例给出了无效的参数类型

    我正在尝试 Firebase 的新 Firestore 当我运行代码示例时https firebase google com docs firestore manage data add data authuser 0 https fire
  • css在表单中浮动2个输入字段

    我在理解 css 时遇到以下问题 我有一张登记表 在这种形式中 我使用字段集 现在我想在每行旁边放置两个输入字段 上面的每个字段还应该有一个标签 所以我想要实现的是 label 1 label 2 label 3 label 4
  • Intellij 自动构建 - 不存在

    如果我删除一个方法 则在我手动构建项目之前 不会显示错误 由于不存在方法而在代码中的其他位置 有没有办法让它在保存 更改时自动构建 我在某个地方缺少一个选项吗 你可以尝试理念 12 EAP http confluence jetbrains
  • TFLite 的硬刷操作

    我有一个用 Tensorflow Keras 编写的自定义神经网络 并应用 Hard swish 函数作为激活 如 MobileNetV3 论文中使用的那样 执行 def swish x return x tf nn relu6 x 3 6
  • 嵌套 jquery 选择器触发父级和子级特定事件

    我有一个具有以下结构的表 表 主 tbody tr Row td 输入 EditRow 我的 jquery 看起来像这样 table Main gt tbody gt tr Row live click function e RowClic
  • PhantomJS/CasperJS AssertExists() 失败

    我试图检查我的网页中是否存在选择器 但 casperjs 从未找到它 我尝试过两种方法 1 无需等待 casper then function search for casperjs from google form this test a
  • 出站 ChannelHandler 的捕获所有异常处理

    在 Netty 中 您有入站和出站处理程序的概念 只需在管道的末尾 尾部 添加一个通道处理程序并实现一个捕获所有入站异常处理程序即可实现exceptionCaught覆盖 如果未沿途处理 沿入站管道发生的异常将沿着处理程序传播 直到遇到最后