领先一步
VMware 提供培训和认证,助您加速进步。
了解更多阅读时间:约 15 分钟。
现在,一些阅读本文的开发者使用 HTTP 已经很多年了。他们中的大多数人也知道,如果你想将 HTTP 与其他消息传递模型一起使用——比如即发即弃(fire-and-forget)——有时你必须使用一些巧妙的变通方法,就像 Stackoverflow 上发布的这个例子。这是因为 HTTP 是一种请求-响应协议(request-response protocol)。它要求发送一个请求并接收一个响应。它没有单向消息的概念,也无需任何形式的响应。
RSocket 采用了不同的方法。RSocket 在 TCP 和 WebSockets 等传输层之上定义了一个新的协议层。这个新协议为开发者提供了更多选择,内置支持四种不同的交互模型:
在之前的文章中,您已经了解了如何使用 RSocket 进行请求/响应通信。在本文中,您将学习如何将即发即弃消息传递添加到您的代码中。让我们直接开始吧!
如果您还没有阅读之前关于 RSocket 的服务器端和客户端请求-响应消息传递的文章,现在是时候了!代码示例在 GitHub 上。
您应该还记得之前您在 rsocket-server
项目中使用的 RSocketController
@Slf4j
@Controller
public class RSocketController {
// code goes here
}
RSocketController
是处理请求-响应消息传递的服务器端类。它的 .requestResponse()
方法接受一个 Message
对象作为参数,并返回一个 Message
对象作为响应。正是这种“一个输入对象,一个输出对象”的方法签名使得该方法成为请求-响应方法。
要向服务器添加即发即弃功能,您必须添加一个具有不同签名的方法。.fireAndForget()
方法应接受单个 Message
参数,但这次应返回 void
,如下所示...
@MessageMapping("fire-and-forget")
public void fireAndForget(Message request) {
log.info("Received fire-and-forget request: {}", request);
}
您仍然必须在方法上使用 @MessageMapping
注解,但这次您必须为 路由 映射指定一个不同的名称。在上面的代码中,我使用了名称 "fire-and-forget"。
在 Spring RSocket 文档中,方法签名规则位于消息映射部分。
您在按照上一篇文章操作时,已经在 rsocket-client
项目中构建了 RSocketShellClient
@Slf4j
@ShellComponent
public class RSocketShellClient {
// code goes here
}
RSocketShellClient 使用 .requestResponse()
方法,通过在类构造函数中创建的 RSocketRequester
向 RSocket 服务器发送单个请求。
要将即发即弃功能添加到您的客户端,请像这样向 RSocketShellClient
添加一个新的 .fireAndForget()
方法
@ShellMethod("Send one request. No response will be returned.")
public void fireAndForget() throws InterruptedException {
log.info("\nFire-And-Forget. Sending one request. Expect no response (check server log)...");
this.rsocketRequester
.route("fire-and-forget")
.data(new Message(CLIENT, FIRE_AND_FORGET))
.send()
.block();
}
让我们更详细地检查此方法中的代码
rsocketRequester
上的 .route()
设置为 "fire-and-forget"
。这个路由名称与 RSocketController
中即发即弃方法上的 @MessageMapping
注解匹配。
一个新的 Message
实例为 .data()
方法提供数据。消息实例的 origin 设置为 CLIENT
,其交互模式设置为 FIRE_AND_FORGET
。
注意,这里没有调用 .retrieveMono()
。相反,即发即弃特定的 .send()
方法将消息发送到服务器,而 .block()
则进行订阅并等待完成。请记住,在响应式代码中,没有订阅就不会发生任何事情。
代码编写部分到此结束。现在,是时候测试它是否正常工作了。
打开一个终端窗口,进入 rsocket-server
目录。使用 Maven Wrapper 启动服务器,如下所示
cd rsocket-server
./mvnw clean package spring-boot:run -DskipTests=true
服务器将在 localhost
的端口 7000
上启动。
有关如何在 Windows 10 上运行 Linux 终端的详细信息,请参阅 Ubuntu 提供的这份快速指南。
打开第二个终端窗口,进入 rsocket-client
目录。然后,按照以下步骤构建并运行客户端应用程序
cd rsocket-client
./mvnw clean package spring-boot:run -DskipTests=true
客户端运行后,Spring Shell 会为您呈现一个新的提示符
shell:>
您可以在提示符下输入 fire-and-forget
将您的即发即弃消息发送到服务器。
shell:>fire-and-forget
2020-02-03 14:54:14.028 INFO 2929 --- [ main] io.pivotal.rsocketclient.RSocketClient :
Fire-And-Forget. Sending one request. Expect no response (check server)...
客户端不会打印任何响应,但如果您切换到服务器的终端窗口,您会注意到即发即弃消息的接收已成功记录到控制台。
2020-02-03 14:54:14.129 INFO 2061 --- [or-http-epoll-2] io.pivotal.rsocketserver.RSocketServer : Received fire-and-forget request: Message(origin=Client, interaction=Fire-And-Forget, index=0, created=1580741654)
您可以通过在 shell:>
提示符下输入 exit 来停止 rsocket-client
。
shell:>exit
您可以通过在 rsocket-server
的终端窗口中按下 Ctrl-C
来停止该进程。
客户端的 .fireAndForget()
方法在调用 block()
方法时,使用 RSocketRequester
向服务器发送单个 Message
。block
方法实际上是一个“订阅并等待”的指令。
服务器端的 RSocketController
会检查消息元数据中的 route
,并将消息正确地传递给 .fireAndForget(Message request)
方法进行处理。一旦客户端发送了请求,它就可以自由地进行其他工作。当服务器接收到请求时,它也可以继续进行其他工作。它无需向客户端发送响应。
在本文中,您学习了如何使用 Spring Boot 和 RSocket 快速构建即发即弃功能。有关 Spring RSocket 集成和消息映射的更多信息,请参阅 Spring RSocket 文档。在下一篇文章中,我们将介绍请求-流消息传递。下篇文章见!