我倾向于web流和反应器。有三种测试方法如下。“docentOperations. findById”和“docentOperations.delete”是两个数据库操作。我知道test1不好,因为两个db操作放在一个异步方法中。我的问题是:
test2和test3对系统性能的影响相同吗?或者换句话说,哪一个更好?
private Mono<ServerResponse> test1(ServerRequest request, Contexts contexts) {
return request.body(bodyDocumentExtractor)
.flatMap(doc -> {
Document document = documentOperations.findById(doc.getId());
documentOperations.delete(document.getId());
return ServerResponse.noContent().build();
});
}
private Mono<ServerResponse> test2(ServerRequest request, Contexts contexts) {
return request.body(bodyDocumentExtractor)
.flatMap(doc -> {
return Mono.just(documentOperations.findById(doc.getId()))
.flatMap(document -> {
documentOperations.delete(document.getId());
return ServerResponse.noContent().build();
});
});
}
private Mono<ServerResponse> test3(ServerRequest request, Contexts contexts) {
return request.body(bodyDocumentExtractor)
.flatMap(doc -> {
return Mono.just(documentOperations.findById(doc.getId()));
}).flatMap(document -> {
documentOperations.delete(document.getId());
return ServerResponse.noContent().build();
});
}
上面的例子都不好。您的所有数据库调用都返回具体类型,这意味着它们都是阻塞调用。
// returns the concrete type
// thread does the call, needs to wait until we get the value (document)
Document document = documentOperations.findById("1");
如果它是非阻塞的,它会返回一个Mono
// Returns a mono, so we know it's not blocking.
// We can chain on actions with for example flatMap etc.
Mono<Document> document = documentOperations.findById("1");
如果你必须使用阻塞数据库,比如oracle数据库等。你需要把它放在它自己的整个线程上,这样它就不会阻塞任何一个主工作线程。这可以用调度程序来完成。所以在这个例子中,当客户端订阅时,它将被放在一个单独的线程上。
Mono<Document> document = Mono.fromCallable(() -> documentOperations.findById("1"))
.subscribeOn(Schedulers.boundedElastic());;
所以对于你的例子:
private Mono<ServerResponse> test3(ServerRequest request, Contexts contexts) {
return request.body(bodyDocumentExtractor)
.flatMap(doc -> Mono.fromCallable(() -> documentOperations.findById(doc.getId()))
.flatMap(document -> Mono.fromCallable(() -> documentOperations.delete(document.getId()))
.then(ServerResponse.noContent().build());
).subscribeOn(Schedulers.boundedElastic());
}
Reactor留档-包装阻塞调用
我希望代码看起来与下面的代码一样,基于DocumentOperation
是反应性的假设。
private Mono<ServerResponse> test3(ServerRequest request, Contexts contexts) {
return request.body(bodyDocumentExtractor)
.flatMap(doc -> documentOperations.findById(doc.getId()))
.flatMap(document -> documentOperations.delete(document.getId()))
.then(ServerResponse.noContent().build());
}