java - 如何测量 webflux WebClient 方法的执行时间?

标签 java spring spring-webflux project-reactor

我准备了一堆要并行发送到外部网络服务的请求。 在此流程中,我继续直接处理响应(例如,将某些内容插入数据库)。

问题:我想跟踪最大请求时间(对于一个请求!),不包括处理。 但正如所写,这只会跟踪全局时间,包括任何子进程:

StopWatch watch = new StopWatch();
watch.start();

Flux.fromIterable(requests)
    .flatMap(req -> webClient.send(req, MyResponse.class)
            .doOnSuccess(rsp -> processResponse(rsp))) //assume some longer routine
    .collectList()
    .block();
    
watch.stop();
System.out.println(w.getTotalTimeMillis());
            

问题:如何测量请求花费的最长时间,不包括 processResponse() 时间?

最佳答案

在单声道上使用 elapsed 时,您会得到元组的单声道,其中包含耗时和原始对象。你必须打开它们才能使用它们。我在测试中写了一个示例(根据您的代码进行了一些简化)以查看它是否正常工作:

@Test
public void elapsed() {

    Flux.fromIterable(List.of(1, 2, 3, 4, 5))
        .flatMap(req -> Mono.delay(Duration.ofMillis(100L * req))
                            .map(it -> "response_" + req)
                            .elapsed()
                            .doOnNext(it -> System.out.println("I took " + it.getT1() + " MS"))
                            .map(Tuple2::getT2)
                            .doOnSuccess(rsp -> processResponse(rsp)))
        .collectList()
        .block();

}

@SneakyThrows
public void processResponse(Object it) {
    System.out.println("This is the response: " + it);
    Thread.sleep(1000);
}

输出看起来像这样:

I took 112 MS
This is the response: response_1
I took 205 MS
This is the response: response_2
I took 305 MS
This is the response: response_3
I took 403 MS
This is the response: response_4
I took 504 MS
This is the response: response_5

这些数字代表延迟(在您的情况下是 webClient.send())和 react 管道本身的一些开销。它是在订阅(当特定请求的 flatMap 运行时发生)和下一个信号(在我的例子中来自 map 的结果,在你的例子中是 webclient 请求的结果)之间计算的

你的代码看起来像这样:

Flux.fromIterable(requests)
        .flatMap(req -> webClient.send(req, MyResponse.class)
                                 .elapsed()
                                 .doOnNext(it -> System.out.println("I took " + it.getT1() + " MS"))
                                 .map(Tuple2::getT2)
                                 .doOnSuccess(rsp -> processResponse(rsp))) //assume some longer routine
        .collectList()
        .block();

请注意,如果您想改用秒表,也可以通过执行以下操作来实现:

Flux.fromIterable(List.of(1, 2, 3, 4, 5)).flatMap(req -> {
            StopWatch stopWatch = new StopWatch();
            return Mono.fromRunnable(stopWatch::start)
                       .then(Mono.delay(Duration.ofMillis(100L * req)).map(it -> "response_" + req).doOnNext(it -> {
                           stopWatch.stop();
                           System.out.println("I took " + stopWatch.getTime() + " MS");
                       }).doOnSuccess(this::processResponse));
        }).collectList().block();

但我个人会推荐 .elapsed() 解决方案,因为它更简洁。

关于java - 如何测量 webflux WebClient 方法的执行时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67062173/

相关文章:

file - spring webflux Flux<DataBuffer> 转换为 InputStream

java - 想法不显示子项目

java - 客户端和服务器的单独控制台 (Java RMI)

java - 验证路径变量大小

spring - 移动设备注册 Spring Social

java - 无法写入 HTTP 消息 : org. springframework.http.converter.HttpMessageNotWritableException:

spring-boot - 如何将 Spring WebClient 与 Jetty 一起使用,而不是 Netty?

spring-webflux - 添加重试WebClient的所有请求

java - 如何使用Dozer在类之间复制数据而不破坏目标类

java - 无法建立 WebSocket 连接 - Spark Java Framework