如何计算Java响应式Spring Boot方法的总执行耗时
解决响应式Spring Boot方法整体执行耗时记录问题
问题原因
你之前的实现中,doFinally被附加在了flatMapMany内部的子Flux上,这会导致日志在内部子Flux完成时就触发,而不是整个verifyStuff方法返回的完整Flux执行完毕时输出。
正确实现方案
把doFinally移到整个Flux链的末尾,确保它监听的是整个方法返回的流的完成信号,同时保持StopWatch的初始化和启动逻辑不变:
public Flux<Void> verifyStuff(){ StopWatch stopWatch = new StopWatch(); stopWatch.start(); return client.getSomeData1(query) .doOnNext(result1 -> log.info("Retrieved '{}' ", result1.size())) .flatMapMany(result1 -> Flux.fromStream(result1.stream()) .concatMap(this::verifyresult1)) .doFinally(signalType -> { stopWatch.stop(); log.info("Total execution time for verifying marketplace partners is {}ms", stopWatch.getTotalTimeMillis()); }); }
关于elapsed()的用法补充
如果需要记录每个元素从订阅到处理完成的耗时,可以用elapsed(),但它不适合直接记录整个流的总耗时:
// 示例:记录每个verifyresult1操作的耗时 public Flux<Void> verifyStuff(){ return client.getSomeData1(query) .doOnNext(result1 -> log.info("Retrieved '{}' ", result1.size())) .flatMapMany(result1 -> Flux.fromStream(result1.stream()) .concatMap(item -> verifyresult1(item) .elapsed() .doOnNext(tuple -> log.info("Processed item in {}ms", tuple.getT1())) .map(Tuple2::getT2))); }
更贴合响应式风格的方案(可选)
如果不想用StopWatch,可以通过AtomicLong记录起始时间,结合doFinally计算总耗时:
public Flux<Void> verifyStuff(){ AtomicLong startTime = new AtomicLong(); return client.getSomeData1(query) .doOnSubscribe(sub -> startTime.set(System.currentTimeMillis())) .doOnNext(result1 -> log.info("Retrieved '{}' ", result1.size())) .flatMapMany(result1 -> Flux.fromStream(result1.stream()) .concatMap(this::verifyresult1)) .doFinally(signalType -> { long totalTime = System.currentTimeMillis() - startTime.get(); log.info("Total execution time for verifying marketplace partners is {}ms", totalTime); }); }
内容的提问来源于stack exchange,提问作者Kartik Kodag
相关产品推荐
相关产品推荐

