首页 > 解决方案 > 由消息队列支持的带有 Spring 的两种方式 RMI

问题描述

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

例如一些签名:

其中响应、请求和数据是我的 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 Integration 我自己的网关,未来可期——太棒了。此外,可以使用 - 丰富消息标题client.id。但是我没有找到合适的方法来处理传入的消息并能够回答它。试图发布一个 ApplicationEvent,但所有事件处理程序都有一个 void 返回类型。所以,我的想法是获取correlationId并发回消息,提供correlationId - 这看起来不是一个明确的解决方案。

  2. RabbitListener/RabbitTemplate 缺点:

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

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

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

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

标签: javaspringmessage-queuermimq

解决方案


那么使用像 RabbitMQ 这样的消息队列或消息代理是一个非常有效的解决方案。但是你必须考虑它是否是你真正需要的。

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

如果您不关心这些功能中的任何一个,而只是想要一种通信结构,那么也许选择一些不同的东西可能更有意义。例如 Akka 提供了基于 actor 的分布式通信

如果困扰您的只是解决方案的清洁度或样板的数量,那么查看其他实现可能会有所帮助。你可能想看看RabbitMQ 的 Reactive Streams API implementation,它应该更抽象一点。


推荐阅读