使用 R2DBC 和无服务器数据库构建完全响应式且可扩展的 Spring 应用程序
使用关系数据库构建真正响应式微服务的挑战
2011年,当响应式应用程序在Java中开始流行时,我经常开玩笑说,用JDBC访问SQL数据库简直就是个完全阻塞的机制。当然,当时人们普遍认为SQL数据库已经过时了,无模式的NoSQL解决方案将在未来五年内成为主流。Spring已经过时了!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 的可扩展性令人印象深刻,因为它是唯一一款提供以下三种选项的云数据库:
我们将使用“无服务器”选项,这样我们就可以以极低的成本构建所有内容:转到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,它是 R2DBC 在 Microsoft SQL Server 上的实现。
我们在使用它时遇到了不少问题,例如这个烦人的 SSL 漏洞,所以我们在这里使用的是快照版本:
<dependency>
<groupId>io.r2dbc</groupId>
<artifactId>r2dbc-mssql</artifactId>
<version>0.8.0.BUILD-20190819.142517-35</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-r2dbc</artifactId>
<version>1.0.0.gh-151-SNAPSHOT</version>
</dependency>
Spring 团队目前正在解决这些问题,一旦稳定版本发布,我们将立即更新示例项目。
Spring 配置 R2DBC
Spring Boot提供了一个Starter来自动配置 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> {
}
因此,我们可以将此存储库用作 REST 端点中的普通 Spring JDBC 或 Spring JPA 存储库:
@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-filled-reactive-and-scalable-spring-application-with-r2dbc-and-a-serverless-database-1jke

