最近,我再次看到,关于反应式编程,尤其是对数据库的反应式工作,炒作已经普遍增加。我想说几句话。
让我提醒您以前的系列中发生了什么。2017年底,Spring 5出现了,其中出现了对反应式编程的支持。特别是,我们在谈论WebFlux。每个人都开始急剧尝试这项技术(典型的炒作曲线),然后业界意识到并非每个人都需要重新激活。获得的主要经验教训:- 反应性编程更难调试
- 开发被动系统比经典的,封闭的系统要困难得多。如果您无意间阻塞了线程,则说明您已完成。这就是该项目出现的原因(其中一位作者-bsideup )
- 主要在Netflix的高负载下需要反应式编程,尤其是弹性。如果您有100 RPS,则可能应该以阻塞方式编写代码-既便宜又容易
此外,每个人都了解另一件事。为了使反应式编程真正展开,您需要整个系统(包括数据库)是反应式的。问题在于数据库甚至可能没有响应式或至少异步的API。是的,也许是这样的API,但您的驱动程序可能不支持它。实际上,当我需要经典的关系数据库时,周围的几乎每个人都在开发PostgreSQL系统。话虽如此,默认选择。我们使用旧的(已有10多年历史的)JDBC驱动程序pgjdbc使用PostgreSQL。这个驱动程序对每个人都有好处。几乎没有错误。此驱动程序的性能得到了极大的改善(为此,弗拉基米尔西尼科夫)但是pgjdbc有一个致命的缺陷- 不支持异步API。近年来,一场激烈的竞赛开始为PostgreSQL开发替代驱动程序,其中包括异步API的开发。甚至Oracle都试图这样做,但是已经结束了对Loom项目及其Fibers的开发。但是,Oracle对此进行了更好的考虑,然后重新开始。现在有3个解决方案:- https://github.com/jasync-sql/jasync-sql-用Kotlin编写的PostgreSQL异步驱动程序,其中Netty是传输
- Vert.x使用的解决方案是https://github.com/mauricio/postgresql-async。值得注意的是,项目已存档,并且以前的jasync-sql驱动程序重写了相同的内容(尽管原始文件是用Scala编写的,而新的解决方案是用Kotlin编写的)。
更新资料 我的评论已得到纠正,来自Vert.x的客户端还活着,并且在基准测试中感觉很好。
- Spring团队的驱动程序是https://github.com/r2dbc/r2dbc-postgresql。该驱动程序立即提供一个响应式API(而非异步),并且像jasync-sql中一样,将Netty用于传输。
从概念上讲,这些驱动程序基于相似的原理。它们全部使用专有的PostgreSQL功能:不幸的是,驱动程序无法更改Wire协议Postgres(好像Oleg Dokuk不想-https: //www.youtube.com/watch?v= n9tL2I_Big8 )。也就是说,Postgres仍然需要一个单独的Connection用于SELECT查询。此外,Postgres还在为每个Connection创建一个新流程-https: //www.postgresql.org/docs/current/tutorial-arch.html。但是,有个好消息。可以批量发送修改请求,而无需等待结果(使用管道)。在这种情况下,每个请求都不需要连接。也就是说,总结一下。响应式(或异步)PG驱动程序改善了应用程序中的情况(我们现在使用基于Netty的非阻塞IO,而不是在查询上花费线程),但特别是在PostgreSQL方面-情况不是很好(希望改善网络协议和数据库架构) )您应该更靠近哪个驱动器?如果像我一样在您的工作中使用Spring,那么r2dbc-postgresql可能是一个不错的选择。重要的是,在最新版本的框架中,Pivotal的人员必须很好地将驱动程序与通常的东西集成在一起,例如与Spring Data R2DBC(这仍然是RC)。结果,我们不必使用低级驱动程序API和连接池,从而减少了在如此复杂的项目中犯错的可能性。使用Spring Data R2DBC的最小示例(我已经在文档中成功完成了侦探)看起来很熟悉:1.配置凭证和连接池:spring.r2dbc.username=postgres
spring.r2dbc.password=P4$$W0RddD
spring.r2dbc.url=r2dbc:postgresql:
spring.r2dbc.pool.enabled=true
spring.r2dbc.pool.initial-size=10
spring.r2dbc.pool.max-idle-time=1m
spring.r2dbc.pool.max-size=30
spring.data.r2dbc.repositories.enabled=true
2.创建一个实体:public class Customer {
@Id
private Long id;
private String firstName;
private String lastName;
public Customer(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
3.创建通常的存储库:public interface CustomerRepository extends ReactiveCrudRepository<Customer, Long> {
}
4.使用存储库:@RestController
@RequestMapping("/")
public class CustomerController {
private CustomerRepository customerRepository;
@PostMapping("/customer")
Mono<Void> create(@RequestBody Publisher<Customer> customerFlux) {
return customerRepository.saveAll(customerFlux).then();
}
@GetMapping("/customer")
public Flux<Customer> list() {
return customerRepository.findAll();
}
@GetMapping("/customer/{id}")
public Mono<Customer> findById(@PathVariable Long id) {
return customerRepository.findById(id);
}
}
可以在此存储库中找到完整的示例-https: //github.com/Hixon10/spring-boot-r2dbc-postgresql-example。最后,让我们谈谈重要的一点:您现在需要在应用程序中使用r2dbc吗?我认为-为时过早。我将等待一系列技术(驱动程序,Spring DATA)发布,并收集一些初衷。我认为,到2021年,将有可能更仔细地研究这个驱动因素。当前的状态-整个反应系统(Spring WebFlux + R2DBC数据库驱动程序)看起来很酷。从字面上看ole发布了摘要,其中有指向具有基准的文章的链接-https: //technology.amis.nl/2020/04/10/spring-blocking-vs-non-blocking-r2dbc-vs-jdbc-and-webflux-vs- web-mvc /。简而言之-反应性胜出。