【问题标题】:Get Reactor Subscriber Context in doOnSubscribe, doOnSuccess and doOnError在 doOnSubscribe、doOnSuccess 和 doOnError 中获取 Reactor 订阅者上下文
【发布时间】:2018-08-21 08:30:05
【问题描述】:

我正在尝试实现 Reactor 订阅者上下文 (http://projectreactor.io/docs/core/release/reference/#context),以便我可以将 SLF4J MDC 中的值传递到 Flux 中,然后我可以使用这些值进行日志记录。

我使用subscriberContext() 方法来设置如下值:

someFlux().subscriberContext(Context.of(MDC_ATTRIBUTE, MDC.get(MDC_ATTRIBUTE)));

我还可以访问链中的上下文。以平面地图为例:

.flatMap(r -> Mono.subscriberContext().map(ctx -> {
    String name = ctx.getOrDefault(MDC_ATTRIBUTE_NAME, "NO CTX");
    return r;
}))

doOnEach() 也有效:

.doOnEach(signal -> {
    Context ctx = signal.getContext();
    if (signal.isOnNext()) {
        try (MDC.MDCCloseable closeable = MDC.putCloseable(MDC_ATTRIBUTE_NAME, ctx.getOrDefault(MDC_ATTRIBUTE_NAME, "MAAAAN"))) {
            log.debug("FINISHED: {}", requestName);
        }
    }
})

只有一个问题。我想在doOnSubscribedoOnErrordoOnSuccess 中记录一些内容。虽然我可以使用 doOnEach 来检查 signal.isOnNext()signal.isOnComplete(),但我发现从未调用过 signal.isOnSubscribe()

所以问题是:我怎样才能获得doOnSubscribe() 中的上下文,或者这根本不可能?

【问题讨论】:

  • 即使Flux 为空,您是否希望引发订阅事件?

标签: spring-boot project-reactor


【解决方案1】:

这是可能的,不是在 100% 的用例中,而且有一点技巧:

Flux.just("foo")
    .doOnSubscribe(sub -> {
        Scannable actual = Scannable.from(sub).scan(Scannable.Attr.ACTUAL);
        if (actual instanceof CoreSubscriber) {
            Context context = ((CoreSubscriber) actual).currentContext();

            System.out.println(context);
        }
    })
    .map(v -> "value: " + v) //below or above doOnSubscribe is fine
    .subscriberContext(Context.of("foo", "bar")) //MUST be below doOnSubscribe
    .blockLast();

【讨论】:

  • doOnCancel() 呢?在这种情况下是否可以访问它?
  • 没有。特别是因为当取消信号到达您的 doOnCancel 时,与持有上下文的实际下游订阅者的联系可能已经被切断
  • 所以目前不可能。这也不可行吗?是否值得为此创建功能请求?
  • 这是反应器的整个架构(以及上下文功能)的结果,因此这不太可能因取消而改变
猜你喜欢
  • 2018-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多