使用关系数据库构建真正的反应性微服务的挑战
2011年,当反应性应用程序开始在Java中变得更常见时,我经常开玩笑说,用JDBC访问SQL数据库是一种完全阻塞的机制。当然,那时人们认为SQL数据库已经过时,无模式的NoSQL解决方案将在未来5年内成为标准。春天已经死了!SQL数据库下一个会死!
在一段古怪的历史转折中,数年后,我们仍然拥有统治着世界的Spring和SQL数据库……但是现在,它们都可以在反应式、云原生和无服务器架构中完美地工作!
在此博客文章中,我们将了解如何使用以下技术构建这样的应用程序:
- Spring Webflux,所以我们有反应性的REST端点
- R2DBC,因此我们使用新的反应式SQL驱动程序,该驱动程序使我们的应用程序能够从数据库到REST端点完全反应
- SQL Server的无服务器版本,因此我们根据需要扩展数据库
警告我们在这里使用的许多技术,包括R2DBC,都是非常新的技术,尚未投入生产。我们正在构建一个可工作的应用程序,我们希望本文将有助于传播和稳定这些技术,但是使用它们的风险由您自己承担!
样例应用
我们在这里开发一个简单的Spring Webflux微服务,该服务与SQL数据库进行通信。最终代码可从GitHub上的https://github.com/jdubois/spring-reactive-sql-server获得。
无服务器SQL Server
并非所有数据库都具有R2DBC的反应式驱动程序,这就是为什么我们在这里选择SQL Server。另一个原因是具有“无服务器”选项,该选项花费很少。实际上,SQL Server的可伸缩性选项令人印象深刻,因为它是唯一具有以下三个选项的云数据库:
- 通过超大规模选项,可实现极高的性能、可用性和存储(最多100 To!)
- 使用弹性数据库池优化价格/性能和可伸缩性
- 使用(我最喜欢的!)无服务器数据库实例,成本极低且按需定价
我们将在此处使用“无服务器”选项,因此我们可以以极低的价格构建所有内容:转到Azure门户并选择“ SQL数据库”:
我们选择了最便宜的选项:我们的数据库每月将花费0.15欧元,再加上每秒使用的0.000067欧元(因此,一小时的时间约为0.24欧元)。这对于开发或测试环境确实非常有用,因为只有在使用时才需要付费。
要创建数据库模式,我们在这里有一个简单的脚本:
CREATE TABLE person (
id BIGINT NOT NULL IDENTITY PRIMARY KEY,
first_name VARCHAR(100),
last_name VARCHAR(100),
company VARCHAR(100)
)
有许多选项可在数据库上运行此脚本,但最简单的方法是使用可通过Azure门户使用的联机编辑器:
R2DBC的用法和配置
R2DBC是Java的反应式驱动程序的规范。更具体地说,我们将使用RD2BC SQL Server,它是Microsoft SQL Server的实现。
我们在使用它时遇到了很多问题,例如这个令人讨厌的SSL bug,这就是为什么我们在这里使用快照版本:
io.r2dbc
r2dbc-mssql
0.8.0.BUILD-20190819.142517-35
org.springframework.data
spring-data-r2dbc
1.0.0.gh-151-SNAPSHOT
Spring团队目前正在解决这些问题,一旦稳定版本可用,我们将更新示例项目。
R2DBC的Spring配置
有一个Spring Boot启动器,可以通过Spring Boot自动配置R2DBC,或者您当然可以手动配置R2DBC,就像我们在这里所做的那样:
@Bean
public MssqlConnectionFactory connectionFactory() {
log.info("Connecting to database '{}'...", host);
return new MssqlConnectionFactory(MssqlConnectionConfiguration.builder()
.host(host)
.port(1433)
.database(database)
.username(username)
.password(password)
.build());
}
Spring Data和R2DBC的数据访问代码
好消息是,Spring Data可以部分地与R2DBC一起使用:您将不具备即时SQL查询生成等所有功能,但是大多数框架都可以使用,这意味着我们可以拥有非常简单的存储库,如下所示:
@Repository
public interface PersonRepository extends ReactiveCrudRepository<Person, Long> {
}
因此,该存储库可以像通常的Spring JDBC或Spring JPA存储库一样,在我们的REST端点中使用:
@RestController
public class PersonController {
private final PersonRepository personRepository;
public PersonController(PersonRepository personRepository) {
this.personRepository = personRepository;
}
@GetMapping("/persons")
public Flux<Person> list() {
return personRepository.findAll();
}
}
结论和最后的想法
我们在此处开发的示例项目可在https://github.com/jdubois/spring-reactive-sql-server上找到。将来,该项目应该使用R2DBC的稳定版本以及其启动程序和连接池项目,但是它已经完全可用。
好消息是,尽管使用了一些非常先进的功能,但是我们的代码仍然看起来像是普通的Spring Boot应用程序:大多数配置和API对Spring用户来说应该是熟悉的,并且可以像任何普通的Spring Boot应用程序一样运行。
此安装程序的杀手级功能是,由于有了SQL Server的“无服务器”版本,又由于有了R2DBC和Spring Webflux,我们才能够拥有一个非常可扩展的应用程序,其成本将根据使用情况而有所不同。在应用程序方面,使用Spring Webflux意味着我们的应用程序启动非常快(在MacBook Pro上超过1秒),并且内存使用受到限制。因此,我们的最终结果是高度可扩展且高效的!
原文链接:https://dev.to//azure/building-a-fully-reactive-and-scalable-spring-application-with-r2dbc-and-a-serverless-database-1jke