查看原文
其他

在微服务中使用RabbitMQ也需要规范化

ImportNew 2021-12-02

(给ImportNew加星标,提高Java技能)

转自:咔咔侃技术,

链接:https://www.toutiao.com/i6824878473710928387/


这篇文章的读者,假设您已经对RabbitMQ、SpringBoot和微服务有一定的理解。此文章来自于对内部技术规范指引的编辑。


典型应用场景



此图展示了 RabbitMQ 的典型应用场景,生产者把消息发送到Exchange,消费者从 Queue 读取消息,消息可通过 topic、header、direct、fanout 四种方式由 Exchange 路由到 Queue。


在微服务中的开发过程中,如果任由开发者定义 Exchange、Queue 以及路由方式,即便优秀的程序员正确定义了这些要素,服务依赖会生成一个巨复杂的网状结构,管理起来必定是灾难。所以要对使用进行规范,这是技术管理应有之意。


通过文档定义规范,这种约束是弱势的,需要不断核查规范的实施情况。通过代码、架构定义规范,在不需要开发者介入的情况下执行规范,屏蔽程序的复杂性,是架构师需要考虑的问题。优秀的架构使开发过程简单化、规范化,使程序员专注业务开发,提升业务开发的效率。


按照这种指导思想,对 RabbitMQ 的使用进行了规范和约束。


微服务应用规范化



约束如下:


  1. 如若服务启用了 Producer,则创建与服务名相同的 Exchange,发送消息到此 Exchange。

  2. 如若服务启用了 Consumer,则创建与服务名相同的 Queue,从此 Queue 中订阅消息。

  3. 读取程序中定义的 Receiver,解析定义的 service (其实就是 Exchange 名字)和 tag,创建 Queue 到 Exchange 的绑定关系。

  4. 以上过程,在服务启动时执行,无需程序员干预。


优点:程序员无需关注消息发给谁,只需要调用服务发送消息即可;程序员无需关注消息如何路由,只需要为自己关心的 tag,定义 receiver 处理类。另外,因为采用统一的 API 发送和接收,为未来的扩展提供了便利。


缺点:每个服务只有一个 Exchange,只有一个 Queue,并且只使用了 Topic 路由;所以,性能并不是最优的,只能在中度或轻度处理场景中使用。如若有个性化的处理场景,还是需要自定义这些组件的。


综述:在 AntSentry 的微服务体系中,大流量量使用了 Kinesis 队列(类kafka),大并发使用了点对点的 SQS 队列,RabbitMQ 只是用来解决服务之间的调用问题,流量并不会太大,其灵活性弥补了 Kinesis 和 SQS 的不足,在这个特有的场景中,满足了业务需求。在大多数的微服务场景中,这种应用模式是可以满足大多数的需求的,希望对你有所帮助。


使用方法


1)修改pom,升级api版本(此项目并未开源,公司内部使用)


<dependency> <groupId>xx</groupId> <artifactId>cloud-api-tools</artifactId> <version>1.3.3-SNAPSHOT</version></dependency>


2)采用自定义 AutoConfig,配置后即按照规范启用了 rabbitmq。


com: xx: rabbitmq: host: 10.30.60.41 password: XX userName: xx port: 5672 vhost: dev


3)创建消息实体


@Datapublic class XXDemoInfo extends MQMessage { @Override public String getTag() { return "work"; // 消息的标识 } private String name; private Long timestamp;}


4)创建接受者,配置消息的来源以及 tag;可配置多个注解,实现一个 receiver 处理多种 tag。


@RabbitMQReceiver(service = "cloud-xx-service", tag = "work") public class XXTagReceiver implements RabbitMQBaseReceiver<XXDemoInfo> { @Override public void receive(XXDemoInfo xxDemoInfo) { }}


5)发送消息示例


@AutowiredRabbitMQSender sender;
public void send() { XXDemoInfo info = new XXDemoInfo(); info.setName("Test Message"); info.setTimestamp(System.currentTimeMillis()); sender.send(info);}


6) 配置 ReceiverScan


@RabbitMQReceiverScan(basePackages = {"com.xx.receiver"}) // 填写receiver类所在的包public class SomeApplication implements CommandLineRunner{
}


实现关键技术


这里感觉没什么好讲的,总不能贴出来大片的代码吧!就把启动过程简单画一下吧。




推荐阅读  点击标题可跳转
RabbitMQ 消费端限流、TTL、死信队列
RabbitMQ 如何实现对同一个应用的多个节点进行广播
SpringBoot+RabbitMQ (保证消息100%投递成功并被消费)


看完本文有收获?请转发分享给更多人

关注「ImportNew」,提升Java技能

好文章,我在看❤️

: . Video Mini Program Like ,轻点两下取消赞 Wow ,轻点两下取消在看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存