Spring WebClient subscribe()块中的日志语句为何未执行?
Spring WebClient非阻塞发送邮件时subscribe日志不生效的解决方法
问题原因
直接手动调用subscribe时,容易出现两种情况导致日志不生效:
- 若当前执行环境是阻塞式的,异步回调的线程可能在日志输出前就结束,或者线程上下文(如MDC链路信息)丢失,导致日志无法正常输出。
- 在Spring反应式编程模型中,手动
subscribe会脱离框架的反应式流管理,回调逻辑的执行稳定性无法保障。
解决方案
方案1:用反应式操作符替代手动subscribe
不要直接调用subscribe,而是使用doOnSuccess和doOnError操作符处理日志逻辑,然后返回Mono交由上层(如WebFlux控制器)统一订阅管理,这是Spring反应式编程的标准做法:
修改调用邮件客户端的Service代码:
logger.info("Sending mail due to failure with id = ${failure.id}, error: $errorMessage") return mailClient.sendMail(Mail(..)) .doOnSuccess { response -> logger.info("success: $response") } .doOnError { error -> logger.error("error: $error") }
如果是在WebFlux控制器中调用该Service方法,直接返回这个Mono即可,框架会自动完成订阅,确保回调逻辑执行:
@PostMapping("/send-mail") fun sendFailureMail(@RequestBody failure: Failure): Mono<Void> { return mailService.sendFailureMail(failure) .then() }
方案2:手动subscribe时保障线程稳定性
如果必须手动调用subscribe(比如在非WebFlux环境),可以通过指定线程池来稳定回调执行,同时确保应用主线程不会提前退出:
logger.info("Sending mail due to failure with id = ${failure.id}, error: $errorMessage") mailClient.sendMail(Mail(..)) .subscribeOn(Schedulers.boundedElastic()) .subscribe( { response -> logger.info("success: $response") }, { error -> logger.error("error: $error") } )
额外检查项
- 确认日志框架(如Logback、Log4j2)的配置正确,
info级别日志已开启,且输出目标(控制台/文件)配置正常。 - 若使用MDC传递链路信息,需确保反应式线程中MDC上下文正确传递(可通过Reactor的
Context或Spring的ReactorContext处理)。
内容的提问来源于stack exchange,提问作者Christian
相关产品推荐
相关产品推荐

