我最近开始在一个新项目中使用 Spring Boot,该项目具有以下代码(简化):
@RestController
@RequestMapping("/users")
public class MyController {
@Autowired
UserService service;
@GetMapping
public Mono<ResponseEntity<User>> getUser() {
// note, the non-reactive call is wrapped into Mono.just
return Mono.just(new ResponseEntity<User>(service.getUser(), ...);
}
}
// both service and dao (below) are non reactive
@Service
public class UserService {
@Autowired
UserDao dao;
User getUser() {
// some logic (everything is in memory, nothing is io-bound)
return dao.getUser();
}
}
@Repository
public class UserDao {
public User getUser() {
// call the non-reactive relational db and get the user
// it takes 99% of the time I believe
// return this user;
}
}
现在我从未真正使用过响应式方法,但我知道这个 Spring Boot 应用程序在幕后必须运行 netty 并使用 webflux 我使用数据库作为 I/O 绑定操作的示例,但有时在代码中还会调用远程服务 (REST),而且它们不是响应式的... 我相信这些数据库操作/远程休息调用占用了 99% 的执行时间,因此这使得该应用程序成为响应式实施的良好候选者。
但是,我对代码的当前情况感到困惑:
我的问题是 - 这种非反应式和反应式方法的混合使用是否可以或错误?
根据我的理解,如果我想采用反应式 Web-flux 方法,我的所有代码都必须一直反应到数据库/远程休息调用(当然包括它们),否则我将有效地保持事件循环netty 的线程很忙,这是我做不到的事情......所以简而言之,这对我来说似乎是错误的,但我不确定这段代码中实际发生了什么。我的理解正确还是我遗漏了什么?
These DB operations/remote rest calls I believe take like 99% of the execution time, so this makes the application to be a good candidate for reactive implementation.
你还有时间。反应式框架并不是为了减少时间。 https://projectreactor.io/docs/core/release/reference/#getting-started-introducing-reactor。
Reactor 是 JVM 的完全非阻塞反应式编程基础,具有高效的需求管理(以管理“背压”的形式)
这是您的用例吗?
The controller is reactive
真的吗?您使用
Mono::just
使其具有反应性,但您使用的是非反应性注释。
The service / DAO / Remote Calls are not
为什么不把它们也换掉呢?如果您需要包装它们,请检查文档。 C.1。如何封装同步、阻塞调用?.
In my understanding if I want to go with reactive web-flux approach, all my code must be reactive all the way down to the database/remote rest call (including them of course), otherwise I'll effectively keep the event-loop threads of netty busy and this is something I can't do... So it seems wrong to me in a nutshell, But I'm not sure what happens actually in this code. Is my understanding correct or I'm missing something?
是的。一直往下。目的是创建一个
flow
并将其传递给客户端。当客户端请求结果时,flow
在响应式框架内执行。
当框架遇到阻塞调用(例如 DB 或 REST)时,它会进行调用并重新调整线程的用途来执行另一个并发请求。使用 apache tomcat,您可以以非常好的时机处理大约 1 或 2000 个并发请求。开箱即用,384。使用 WebFlux 30 到 5 万。您是否有足够多的用户,他们每秒会发出稳定的 30K 并发请求?我还没有看到不只是切换到 C++ 的用例。
它也包含在
functional
编程范式风格中。很少有人用这种范式编写出好的代码。我刚刚修复了一段 20 行深的代码块,只是为了将一堆叶节点添加到地图中。将其替换为几个 forEach
循环。
享受这个兔子洞的乐趣。人们喜欢新事物,因为它充满异国情调且令人着迷。等到你需要维护某人的代码时才真正理解框架及其用途。
Functional
实在太丑了。