使用publishOn时如何获取Reactor响应式流的线程执行日志?
如何获取Reactor Flux中Scheduler的线程执行日志及背压请求量说明
我来帮你解决这两个核心问题:一是怎么看到线程执行的日志信息,二是解释日志里请求数量变化的原因。
1. 搞定线程执行日志的两种方法
方法一:调整日志配置,显示线程名称
你当前用的slf4j-maven-plugin-log只是把SLF4J绑定到了Maven的日志系统,但默认输出格式没包含线程信息。咱们可以通过Maven插件配置,把线程名加到日志里:
在pom.xml的build节点下添加Surefire插件的日志配置:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.2.5</version> <configuration> <systemPropertyVariables> <org.slf4j.simpleLogger.defaultLogLevel>info</org.slf4j.simpleLogger.defaultLogLevel> <org.slf4j.simpleLogger.showThreadName>true</org.slf4j.simpleLogger.showThreadName> <org.slf4j.simpleLogger.logFile>System.out</org.slf4j.simpleLogger.logFile> </systemPropertyVariables> </configuration> </plugin> </plugins> </build>
配置完之后,日志就会显示每条日志对应的线程名,你就能清楚看到publishOn切换到的parallel-n系列线程(Schedulers.parallel()创建的线程池,线程命名是parallel-1、parallel-2这类)。
方法二:直接在流操作中打印线程信息
要是不想改全局日志配置,也可以在Flux的操作符里手动打印线程名,比如在map或者doOnNext里加一行:
Flux.range(1, 1000) .log() .map(i -> { System.out.println("Map操作执行线程: " + Thread.currentThread().getName()); return i * 2; }) .publishOn(Schedulers.parallel()) .doOnNext(i -> System.out.println("订阅消费执行线程: " + Thread.currentThread().getName())) .subscribe(elements::add);
这样就能直观看到每个环节的执行线程,特别是publishOn之后的下游操作,确实跑在并行线程池里。
关于请求数量(256/192)的解释
你看到的request(256)和request(192)是Reactor背压机制的正常表现,不用慌:
- 初始订阅时,下游会向上游请求默认的预取量(
prefetch),默认值就是256,这就是第一个request(256)的由来。 - 当处理完一批元素后,Reactor会根据剩余的处理能力补充请求,补充的数量是
prefetch - (prefetch / 4),也就是256减64等于192,这就是后续request(192)的原因。 - 如果你想自定义这个预取量,也可以在
publishOn里手动指定,比如publishOn(Schedulers.parallel(), 128),这样初始请求量就变成128,后续补充的就是96了。
另外再提一句:publishOn只影响它下游的操作符执行线程,而你注释掉的subscribeOn是影响整个流的上游执行线程,要是打开它,上游的range和map也会跑到并行线程池里。
内容的提问来源于stack exchange,提问作者KayV
相关产品推荐
相关产品推荐

