具有消息队列支持的Spring双向RMI

时间:2019-03-25 14:52:02

标签: java spring message-queue rmi mq

系统由1个或多个客户端和一个服务器组成。每个客户端都是手动添加的,并带有标识符(client.id)。每个客户端都可以将消息发送到服务器。服务器可以向每个客户端发送消息。所有消息都可以分为两组:有答案和无答案。

例如一些签名:

  • CompletableFuture<Response> call(Request requestToServer)
  • void execute(Data dataToSend)

其中Response,Request和Data是我的POJO。

因此,我需要某种RMI来实现服务器与客户端之间的消息通信。

要求:

  1. 服务器在处理消息时必须能够通过其ID client.id来识别客户端,但是客户端在发送该消息之前不应直接填充该标识符;
  2. 消息应为POJO;
  3. 能够回答例外消息;
  4. 事件驱动的处理程序(如@RabbitListener)-多个处理程序-每种传入消息类型的Spring bean,带有或不带有返回类型。处理程序应根据传入的消息类型自动解析;
  5. 由RabbitMQ或ArtemisMQ支持;
  6. 用于从服务器向客户端发送消息的单一服务:发送消息时应提供客户端ID。例如:void sendToClient(int clientId, Data dataToClient)

我尝试设置这种通信方式的方法:

  1. Spring集成 我自己的网关,具有可实现的未来-太好了。此外,还可以使用client.id来丰富邮件标题。但是我没有找到合适的方法来处理传入的消息并能够对其进行应答。试图发布ApplicationEvent,但是所有事件处理程序都具有void返回类型。因此,我在这里的想法是获取correlationId并发送回消息,并提供该correlationId,这似乎不是一个明确的解决方案。

  2. RabbitListener / RabbitTemplate 缺点:

    • 用于设置RabbitTemplate发送和接收消息的大量代码;
    • 需要手动设置请求和答复队列以及绑定;
    • 在@RabbitHandler内部解析client.id的问题。
  3. AmqpProxyFactoryBean 与我的需求最接近的结果,但有几个我无法解决的问题:

    • 在消息处理程序上解决client.id
    • 每个服务接口方法的单个处理程序。

因此,我需要一个轻量级的解决方案来建立由消息队列支持的服务之间的通信。添加其他消息类型应该很容易-声明类,将处理程序添加到使用者,并创建该类的对象并从生产者发送。

但是关于服务通信,也许我完全错了?也许我不应该为此目的使用消息队列?

1 个答案:

答案 0 :(得分:0)

很好地使用消息队列或RabbitMQ这样的消息代理。但是您必须考虑这是否是您真正需要的。

消息代理允许您使消息的生产者和使用者分离。它还允许您引入一定程度的容错能力。如果消费者暂时不可用,则消息不会丢失。但是,这也意味着,如果期望得到答复,则消息的生成者可能会错误地认为另一端已处理了其请求并继续等待答复。消息代理通常还提供某种保证,例如一次或一次或最少一次,并且还规定如何处理无法传递的消息(如死信队列),生存时间和各种路由功能(例如一致的基于哈希的路由)。在您的情况下,如果服务器起源的消息仅到达一个客户端,则可能必须通过带有您的client.id的某些标头值进行路由。

如果您不关心这些功能中的任何一个,而只想要一个通信结构,那么也许做些不同的事情可能更有意义。例如,Akka提供了actor-based distributed communication

如果困扰您的仅仅是解决方案的整洁程度或样板的数量,也许看看其他实现可能会有所帮助。您可能想看看Reactive Streams API implementation for RabbitMQ,它应该更抽象一些。