RSocket 入门:Spring Boot 即发即弃

工程 | Ben Wilcock | 2020 年 3 月 16 日 | ...

阅读时间:约 15 分钟。

现在,一些阅读本文的开发者使用 HTTP 已经很多年了。他们中的大多数人也知道,如果你想将 HTTP 与其他消息传递模型一起使用——比如即发即弃(fire-and-forget)——有时你必须使用一些巧妙的变通方法,就像 Stackoverflow 上发布的这个例子。这是因为 HTTP 是一种请求-响应协议(request-response protocol)。它要求发送一个请求并接收一个响应。它没有单向消息的概念,也无需任何形式的响应。

RSocket 采用了不同的方法。RSocket 在 TCP 和 WebSockets 等传输层之上定义了一个新的协议层。这个新协议为开发者提供了更多选择,内置支持四种不同的交互模型:

  • 请求/响应 (request/response)
  • 即发即弃 (fire-and-forget)
  • 请求/流 (request/stream)
  • 通道 (channel)

在之前的文章中,您已经了解了如何使用 RSocket 进行请求/响应通信。在本文中,您将学习如何将即发即弃消息传递添加到您的代码中。让我们直接开始吧!

如果您还没有阅读之前关于 RSocket 的服务器端客户端请求-响应消息传递的文章,现在是时候了!代码示例在 GitHub 上

步骤 1:添加服务器端即发即弃方法

您应该还记得之前您在 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 文档中,方法签名规则位于消息映射部分。

步骤 2:添加客户端即发即弃方法

您在按照上一篇文章操作时,已经在 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() 则进行订阅并等待完成。请记住,在响应式代码中,没有订阅就不会发生任何事情。

代码编写部分到此结束。现在,是时候测试它是否正常工作了。

步骤 3:构建并运行 RSocket 服务器

打开一个终端窗口,进入 rsocket-server 目录。使用 Maven Wrapper 启动服务器,如下所示

cd rsocket-server
./mvnw clean package spring-boot:run -DskipTests=true

服务器将在 localhost 的端口 7000 上启动。

有关如何在 Windows 10 上运行 Linux 终端的详细信息,请参阅 Ubuntu 提供的这份快速指南

步骤 4:构建并运行 RSocket 客户端

打开第二个终端窗口,进入 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)

步骤 5:清理

您可以通过在 shell:> 提示符下输入 exit 来停止 rsocket-client

shell:>exit

您可以通过在 rsocket-server 的终端窗口中按下 Ctrl-C 来停止该进程。

工作原理

客户端的 .fireAndForget() 方法在调用 block() 方法时,使用 RSocketRequester 向服务器发送单个 Messageblock 方法实际上是一个“订阅并等待”的指令。

服务器端的 RSocketController 会检查消息元数据中的 route,并将消息正确地传递给 .fireAndForget(Message request) 方法进行处理。一旦客户端发送了请求,它就可以自由地进行其他工作。当服务器接收到请求时,它也可以继续进行其他工作。它无需向客户端发送响应。

总结

在本文中,您学习了如何使用 Spring Boot 和 RSocket 快速构建即发即弃功能。有关 Spring RSocket 集成和消息映射的更多信息,请参阅 Spring RSocket 文档。在下一篇文章中,我们将介绍请求-流消息传递。下篇文章见!

获取 Spring 新闻简报

通过 Spring 新闻简报保持联系

订阅

领先一步

VMware 提供培训和认证,助您加速进步。

了解更多

获取支持

Tanzu Spring 通过一项简单的订阅,即可为 OpenJDK™、Spring 和 Apache Tomcat® 提供支持和二进制文件。

了解更多

近期活动

查看 Spring 社区的所有近期活动。

查看全部