RPC over STOMP使用Spring,并正确处理服务器端错误传播到客户端



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

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

当然,当只有一个请求时没有问题,客户端等待它的回复,但是当客户端必须跟踪多个"打开"rpc调用时,问题就出现了。

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

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

  • 我必须开发需要理解此结构的代码,这违背了具有简单注释方法的实用程序

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

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

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

我发现这是一个普遍的问题,我认为Spring在本地实现它会受益匪浅。

这不是你所需要的,但也许你可以尝试这样做:Spring WebSockets中的路径变量@SendTo mapping

你在你的客户端定义一个ID并发送ID到queue/user/queue/{myid}在服务器端,您将有一个类,看起来像这样:

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

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

如果您不需要客户端上的异常/原因,而只想知道哪个消息失败,您可以为成功的消息发送ack消息。对于成功的消息,您总是可以轻松访问消息id/header。通过缺少ack消息,客户端知道哪个消息失败了。

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

相关内容

最新更新