Springboot2.2.6中的RSocket使用, RSocket 进行反应式数据传输

在微服务架构中,不同服务之间通过应用协议进行数据传输。典型的传输方式包括基于 HTTP 协议的 REST 或 SOAP API 和基于 TCP 字节流的 gRPC 等。HTTP 协议的优势在于其广泛的适用性,有非常多的服务器和客户端实现的支持,但 HTTP 协议本身比较简单,只支持请求-响应模式。gRPC 等基于 TCP 的协议使用二进制字节流传输,保证了传输的效率。不过 gRPC 基于 HTTP/2,不支持其他传输层实现。HTTP/2 协议使用了二进制字节流,但是并没有改变 HTTP/1 协议已有的语义,更多的只是改变了传输时的格式。已有应用协议的问题在于单一的交互模式,只支持请求-响应模式,而此模式对于很多应用场景来说是不合适的。典型的例子是消息推送,以 HTTP 协议为例,如果客户端需要获取最新的推送消息,就必须使用轮询。客户端不停的发送请求到服务器来检查更新,这无疑造成了大量的资源浪费。虽然服务器发送事件(Server-Sent Events,SSE)可以用来推送消息,不过 SSE 是一个简单的文本协议,仅提供有限的功能。此外,WebSocket 可以进行双向数据传输,不过它没有提供应用层协议支持。请求-响应模式的另外一个问题是,如果某个请求的响应时间过长,会阻塞之后的其他请求的处理。RSocket 协议的出现,很好的解决了已有协议的这些问题。

RSocket 介绍

RSocket 是一个 OSL 七层模型中 5/6 层的协议,是 TCP/IP 之上的应用层协议。RSocket 可以使用不同的底层传输层,包括 TCP、WebSocket 和 Aeron。TCP 适用于分布式系统的各个组件之间交互,WebSocket 适用于浏览器和服务器之间的交互,Aeron 是基于 UDP 协议的传输方式,这就保证了 RSocket 可以适应于不同的场景。使用 RSocket 的应用层实现可以保持不变,只需要根据系统环境、设备能力和性能要求来选择合适的底层传输方式即可。RSocket 作为一个应用层协议,可以很容易在其基础上定义应用自己的协议。此外,RSocket 使用二进制格式,保证了传输的高效,节省带宽。而且,通过基于反应式流语义的流控制,RSocket 保证了消息传输中的双方不会因为请求的压力过大而崩溃。

RSocket 交互模式

RSocket 支持四种不同的交互模式,见表 1。

表 1. RSocket 支持的四种交互模式

模式 说明
请求-响应(request/response) 这是最典型也最常见的模式。发送方在发送消息给接收方之后,等待与之对应的响应消息。
请求-响应流(request/stream) 发送方的每个请求消息,都对应于接收方的一个消息流作为响应。
发后不管(fire-and-forget) 发送方的请求消息没有与之对应的响应。
通道模式(channel) 在发送方和接收方之间建立一个双向传输的通道。

下面介绍 RSocket 协议的具体内容。

RSocket 帧

RSocket 协议在传输时使用帧(frame)来表示单个消息。每个帧中包含的可能是请求内容、响应内容或与协议相关的数据。一个应用消息可能被切分成多个片段(fragment)以包含在一个帧中。根据底层传输协议的不同,一个表示帧长度的字段可能是必须的。由于 TCP 协议没有提供帧支持,所以 RSocket 的帧长度字段是必须的。对于提供了帧支持的传输协议,RSocket 帧只是简单的封装在传输层消息中;对于没有提供帧支持的传输协议,每个 RSocket 帧之前都需要添加一个 24 字节的字段表示帧长度。

RSocket 帧的内容

在每个 RSocket 帧中,最起始的部分是帧头部,包括 31 字节的流标识符,6 字节的帧类型和 10 字节的标志位。RSocket 协议中的流(stream)表示的是一个操作的单元。每个流有自己唯一的标识符。流标识符由发送方生成。值为 0 的流标识符表示与连接相关的操作。客户端的流标识符从 1 开始,每次递增 2;服务器端的流标识符从 2 开始,每次递增 2。在帧头部之后的内容与帧类型相关。

RSocket 帧的类型

RSocket 中定义了不同类型的帧,见表 2。

表 2. RSocket 中的帧类型

帧类型 说明
SETUP 由客户端发送来建立连接,流标识符为 0。
REQUEST_RESPONSE 请求-响应模式中的请求内容。
REQUEST_FNF 发后不管模式中的请求内容。
REQUEST_STREAM 请求-响应流模式中的请求内容。
REQUEST_CHANNEL 通道模式中的建立通道的请求。发送方只能发一个 REQUEST_CHANNEL 帧。
REQUEST_N 基于反应式流语义的流控制,相当于反应式流中的 request(n)。
PAYLOAD 表示负载的帧。通过不同的标志位来表示状态。NEXT 标志位表示接收到流中的数据,COMPLETE 标志位表示流结束。
ERROR 表示连接层或应用层错误。
CANCEL 取消当前请求。
KEEPALIVE 表示连接层或应用层错误。
KEEPALIVE 启用租约模式。
METADATA_PUSH 异步元数据推送。
RESUME 在连接中断后恢复传输。
RESUME_OK 恢复传输成功。
EXT 帧类型扩展。

RSocket 中的负载分成元数据和数据两种,二者可以使用不同的编码方式。元数据是可选的。帧头部有标志位指示帧中是否包含元数据。某些特定类型的帧可以添加元数据。

RSocket 帧交互

根据不同的交互模式,发送方和接收方之间有不同的帧交互,下面是几个典型的帧交互示例:

  • 在请求-响应模式中,发送方发送 REQUEST_RESPONSE 帧,接收方发送 PAYLOAD 帧并设置 COMPLETE 标志位。
  • 在发后不管模式中,发送方发送 REQUEST_FNF 帧。
  • 在请求-响应流模式中,发送方发送 REQUEST_STREAM 帧,接收方发送多个 PAYLOAD 帧。设置 COMPLETE 标志位的 PAYLOAD 帧表示流结束。
  • 在通道模式中,发送方发送 REQUEST_CHANNEL 帧。发送方和接收方都可以发送 PAYLOAD 帧给对方。设置 COMPLETE 标志位的 PAYLOAD 帧表示其中一方的流结束。

除了发后不管模式之外,其余模式中的接收方都可以通过 ERROR 帧或 CANCEL 帧来结束流。

流控制

RSocket 使用 Reactive Streams 语义来进行流控制(flow control),也就是 request(n)模式。流的发送方通过 REQUEST_N 帧来声明它允许接收方发送的 PAYLOAD 帧的数量。REQUEST_N 帧一旦发出就不能收回,而且所产生的效果是累加的。比如,发送方发送 request(2)和 request(3)帧之后,接收方允许发送 5 个 PAYLOAD 帧。

除了基于 Reactive Streams 语义的流程控制之外,RSocket 还可以使用租约模式。租约模式只是限定了在某个时间段内,请求者所能发送的最大请求数量。

Java 实现

RSocket 提供了不同语言的实现,包括 Java、Kotlin、JavaScript、Go、.NET 和 C++ 等。对 Java 项目来说,只需要添加相应的 Maven 依赖即可。RSocket 的 Java 实现库都在 Maven 分组 io.rsocket 中。其中常用的库包括核心功能库 rsocket-core 和表 3中列出的传输层实现。本文中使用的版本是 1.0.0-RC3。

表 3. RSocket 的传输层实现

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Spring Boot在同一个应用使用MySQL和MongoDB双数据源可以通过以下步骤实现: 1. 添加依赖 在pom.xml文件添加MySQL和MongoDB的依赖: ```xml <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.10</version> </dependency> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> <version>3.12.7</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>2.2.6.RELEASE</version> </dependency> ``` 2. 配置数据源 在application.properties文件配置MySQL和MongoDB的数据源: ```properties spring.datasource.url=jdbc:mysql://localhost:3306/dbname?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.druid.initial-size=5 spring.datasource.druid.min-idle=5 spring.datasource.druid.max-active=20 spring.datasource.druid.test-on-borrow=true spring.datasource.druid.test-while-idle=true spring.datasource.druid.time-between-eviction-runs-millis=60000 spring.datasource.druid.validation-query=select 1 from dual spring.data.mongodb.uri=mongodb://localhost:27017/dbname ``` 3. 配置数据源连接池 在application.properties文件配置Druid连接池: ```properties spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.druid.filters=stat,wall spring.datasource.druid.connection-properties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 ``` 4. 配置JdbcTemplate和MongoTemplate 在Spring Boot应用程序,可以使用JdbcTemplate和MongoTemplate来访问MySQL和MongoDB数据源。 ```java @Configuration public class DataSourceConfig { @Bean @ConfigurationProperties(prefix = "spring.datasource") public DataSource dataSource() { return DruidDataSourceBuilder.create().build(); } @Bean public JdbcTemplate jdbcTemplate(DataSource dataSource) { return new JdbcTemplate(dataSource); } @Bean public MongoTemplate mongoTemplate(MongoDbFactory mongoDbFactory, MappingMongoConverter mappingMongoConverter) { return new MongoTemplate(mongoDbFactory, mappingMongoConverter); } } ``` 5. 使用数据源 在需要使用MySQL和MongoDB数据源的类,注入JdbcTemplate和MongoTemplate,并使用它们来访问数据库。 ```java @Service public class UserService { @Autowired private JdbcTemplate jdbcTemplate; @Autowired private MongoTemplate mongoTemplate; public void addUser(User user) { // 使用JdbcTemplate访问MySQL数据源 jdbcTemplate.update("INSERT INTO user (id, username, password) VALUES (?, ?, ?)", user.getId(), user.getUsername(), user.getPassword()); // 使用MongoTemplate访问MongoDB数据源 mongoTemplate.save(user); } } ``` 以上就是使用Spring Boot和Druid实现MySQL和MongoDB双数据源的步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值