使用Spring实现基于STOMP的RPC,并正确处理传播给客户端的服务器端错误

12

我需要在javascript浏览器客户端上实现RPC over STOMP,并使用Spring消息功能实现服务器端。

对于普通消息使用@MessageMapping很好,但我发现在实现RPC时使用@SendToUser会有限制,因为当客户端同时发出多个请求时,客户端很难理解哪个回复与哪个请求相关。

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

我成功地通过与每个请求关联的ID来解决了这个问题,例如:客户端将id与消息一起发送,服务器回复一个特殊的消息包装,其中包含此id,因此客户端能够将异步的回复与请求关联起来。

这样做很好,但有几个限制:

  • 我必须编写代码来理解此结构,这样就无法使用简单的注释方法

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

我知道使用rabbitmq可以为每个需要与特定回复(rpc响应)关联的请求添加“回复到”头文件,并通过创建一个特殊的临时队列来实现,用户会自动订阅该队列,但我如何在Spring中使用此方案?而且,这将束缚我于特定的代理。

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

我认为这是一个普遍的问题,我认为Spring可以从本质上实现它。


这里概述了一种需要修改Spring类的临时解决方案:https://github.com/spring-projects/spring-framework/pull/612我仍然对不需要修改Spring的解决方案感兴趣。 - Alessandro Polverini
2个回答

1
这不完全是您要求的内容,但也许您可以尝试类似于以下方式: Spring WebSockets中的路径变量@SendTo映射 您在客户端上定义一个ID并将其发送到队列/user/queue/{myid} 在服务器端,您将拥有一个类,看起来像这样:
@MessageMapping("/user/queue/{myid}")
public void simple(@DestinationVariable String id, Object requestDto) {
    simpMessagingTemplate.convertAndSendToUser(userId, "/user/queue/" + id, responseDto);
}

这个解决方案的原理与你提到的RabbitMQ解决方案相同。希望这可以帮到你。

谢谢你的提示,但这不是我要找的,因为需要手动处理“myid”变量:这应该由框架完成。 - Alessandro Polverini
我的解决方案看起来像兔子MQ的解决方案,但你给我点了踩。不太好。 - Oreste Viron
那是我的失误,抱歉。 请编辑答案并添加关于RabbitMQ的信息,我会撤销投票。 - Alessandro Polverini

0

如果在客户端不需要异常/原因,但只想知道哪个消息失败了,您可以为成功的消息发送确认消息。对于成功的消息,您始终可以轻松访问消息ID/标头。通过缺少确认消息,客户端知道哪条消息失败了。

当然,这会带来发送所有确认消息和了解请求超时的成本。此外,还需要额外的代码在客户端跟踪,但可以使用中间件完成,从而获得业务逻辑的良好开发体验。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接