12

我需要通过 STOMP 实现 RPC,其中客户端在浏览器中使用 javascript 运行,而服务器端使用 Spring 消息传递功能实现。

虽然使用@MessageMapping 对于正常的消息传递来说很好,但我发现使用@SendToUser 对实现RPC 有很大的限制,因为在从客户端发出多个同时请求的场景中,客户端很难理解哪个回复与哪个请求相关联。

当然,只发出一个请求,并且客户端等待其回复时没有问题,但是当客户端必须跟踪多个“打开”的 rpc 调用时,就会出现问题。

通过将 ID 与每个请求相关联,我已经设法使系统基本正常,即:客户端将一个 ID 与消息一起发送,服务器使用包含此 ID 的特殊消息包装器进行回复,因此客户端能够将异步回复与请求相关联。

这工作正常,但有几个限制:

  • 我必须开发需要理解这种结构的代码,并且无法使用简单的带注释的方法

  • 当服务器端代码生成异常时,会调用 Spring @MessageExceptionHandler 并将正确的异常返回给客户端,但请求 ID 会丢失,因为处理程序没有(简单的)方法可以访问它。

我知道,使用rabbitmq,我们可以将“reply-to”标头添加到需要与特殊回复(rpc 响应)关联的每个请求中,这是通过创建用户自动订阅的特殊临时队列来实现的,但是我如何在 Spring 中使用这个方案呢?此外,这将使我与一个特定的经纪人联系在一起。

如何在 Spring 中优雅地实现正确处理服务器端异常的正确 RPC 调用?

我发现这是一个普遍的问题,我认为 Spring 可以极大地受益于本机实现它。

4

2 回答 2

1

这不完全符合您的要求,但也许您可以尝试这样的事情: Spring WebSockets @SendTo 映射中的路径变量

您在客户端上定义一个 ID 并将 id 发送到队列 /user/queue/{myid} 在服务器端,您将有一个如下所示的类:

@MessageMapping("/user/queue/{myid}")
public void simple(@DestinationVariable String id, Object requestDto) {
    simpMessagingTemplate.convertAndSendToUser(userId, "/user/queue/" + id, responseDto);
}

该解决方案可以使用与您提到的 rabbit mq 解决方案相同的原理。

希望这可以帮助。

于 2016-06-13T10:10:04.453 回答
0

如果您不需要客户端上的异常/原因,而只想知道哪个消息失败,您可以发送成功消息的 ack 消息。对于成功的消息,您始终可以轻松访问消息 ID/标题。由于没有确认消息,客户端知道哪个消息失败了。

当然,这是以发送所有 ack 消息和知道请求超时为代价的。还需要额外的代码来跟踪客户端,但这可以使用中间件来完成,并且最终会为业务逻辑提供良好的开发体验。

于 2020-04-02T17:46:14.027 回答