Spring boot 如何在SpringBoot2中通过阻塞调用解决吞吐量慢的问题?
我使用SpringBoot2和路由器功能,如果没有阻塞代码,一切都很好,但如果我阻塞了2秒钟,那就太糟糕了。我的应用程序无法访问大量并发用户,也无法提高吞吐量 Doc有一个部分,但这种方法不能解决问题Spring boot 如何在SpringBoot2中通过阻塞调用解决吞吐量慢的问题?,spring-boot,asynchronous,project-reactor,throughput,Spring Boot,Asynchronous,Project Reactor,Throughput,我使用SpringBoot2和路由器功能,如果没有阻塞代码,一切都很好,但如果我阻塞了2秒钟,那就太糟糕了。我的应用程序无法访问大量并发用户,也无法提高吞吐量 Doc有一个部分,但这种方法不能解决问题 return serverRequest .bodyToMono(ValueDto.class) .doOnNext(order -> log.info("get order request " + order))
return serverRequest
.bodyToMono(ValueDto.class)
.doOnNext(order -> log.info("get order request " + order))
.map(i -> {
log.info("map 1 " + requestId);
return i;
})
.map(i -> {
log.info("map 2 " + requestId);
return i;
})
.map(i -> {
log.info("map 3 " + requestId);
return i;
})
.flatMap(i -> Mono.fromCallable(() -> executeLongMethod(i, requestId))
.subscribeOn(Schedulers.elastic()))
.map(v -> {
log.info("map 5 " + requestId);
return v;
})
.flatMap(req -> ServerResponse.ok().build());
private ValueDto executeLongMethod(final ValueDto dto, final String requestId) {
final long start = System.currentTimeMillis();
try {
log.info("start executeLongMethod. requestId:" + requestId);
TimeUnit.MILLISECONDS.sleep(1500);
return dto;
} catch (InterruptedException e) {
e.printStackTrace();
return dto;
} finally {
log.info("finish executeLongMethod requestId:" + requestId + " executed in " + (System.currentTimeMillis() - start) + "ms.");
}
}
我创建了简单的springboot2应用程序,在其中重新创建了问题
return serverRequest
.bodyToMono(ValueDto.class)
.doOnNext(order -> log.info("get order request " + order))
.map(i -> {
log.info("map 1 " + requestId);
return i;
})
.map(i -> {
log.info("map 2 " + requestId);
return i;
})
.map(i -> {
log.info("map 3 " + requestId);
return i;
})
.flatMap(i -> Mono.fromCallable(() -> executeLongMethod(i, requestId))
.subscribeOn(Schedulers.elastic()))
.map(v -> {
log.info("map 5 " + requestId);
return v;
})
.flatMap(req -> ServerResponse.ok().build());
private ValueDto executeLongMethod(final ValueDto dto, final String requestId) {
final long start = System.currentTimeMillis();
try {
log.info("start executeLongMethod. requestId:" + requestId);
TimeUnit.MILLISECONDS.sleep(1500);
return dto;
} catch (InterruptedException e) {
e.printStackTrace();
return dto;
} finally {
log.info("finish executeLongMethod requestId:" + requestId + " executed in " + (System.currentTimeMillis() - start) + "ms.");
}
}
通过Jmeter执行自动负载测试。It设置:
线程组:
线程数:测试期间要运行的并发线程数:30
爬升周期:在此时间内,线性增加负载从0到目标负载:1
循环计数:永远
后请求:{
“valueA”:“假”,
“valueB”:“假”,
“valueC”:“假”
}
结果:
可以找到代码示例不要使用
线程。睡眠
。。。以非阻塞方式睡眠(使用delayElement
)。这样,您将阻止处理和.or请求处理线程,甚至可能阻止整个反应线程,从而导致您停止。谢谢,但在本例中,thread.sleep
-示例。我可以调用soap或其他阻塞操作。我尝试了.flatMap(I->Mono.just(I).delayElement(Duration.ofMillis(1500))
但它并没有提高吞吐量。如果所有可用线程都被阻塞,那么当然什么也不会发生。最终,一切都将被阻止,通常采用反应式方法,您可以有较少的线程来完成相同的工作量。@M.Deinum当然,阻止API不适合此并发模型。但是当chain调用Schedulers.elastic()-时,它会在不同的线程上继续处理,因为会将处理切换到不同的线程池。我认为这可以改善情况。你们有多少个CPU?