1. Reactor Hooks.onErrorDropped 与 onOperatorError 的差异化处理策略?
在 Project Reactor 中,Hooks.onErrorDropped 与 Hooks.onOperatorError 这两个全局钩子的作用分别是什么?它们应该在什么场景下使用,处理策略有何差异?
- 全局错误钩子(Global Hooks)的注册机制与适用场景
- onErrorDropped 与 onOperatorError 的触发时机差异
- 生产环境监控与错误兜底的最佳实践
Reactor 提供了两类全局错误钩子用于兜底处理无法被正常传递的错误。onOperatorError 在操作符执行过程中出现异常、且该异常无法沿正常 onError 路径传递时被调用,例如在 map 等操作符内部抛出的异常已经通过 onError 传递,但某些操作符(如 onNext 内部调用再次抛错)的场景会回调它,通常用于记录日志、附加上下文或做统一采样。onErrorDropped 则发生在某个错误无法被任何下游订阅者接收时,最典型的场景是下游因 cancel 已经取消,而上游仍然推送了一个 onError 信号,此时该错误会被"丢弃"并交给该钩子处理;此外在 onNext 发生时下游已取消也会触发 onErrorDropped。两者都属于"最后防线"性质的兜底机制,不应被用来替代正常的操作符级错误处理,更多是用于可观测性,例如在日志或 APM 中标记"被丢弃的错误"。
理解两者的关键在于"错误能否被正常传递"。onErrorDropped 处理的是"想传但没人接收"的错误(通常是下游已取消),onOperatorError 处理的是"操作符执行过程中产生的、需要被包装或记录"的错误。生产环境应始终注册这两个钩子,避免异常被静默吞掉导致排查困难。
Hooks.onErrorDropped(err -> log.warn("Dropped error: {}", err.toString()));
Hooks.onOperatorError((err, data) -> {
log.error("Operator error on data={}", data, err);
return err;
});