马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
1. fanout模式
Fanout 交换器(Exchange)是 RabbitMQ 中的一种消息路由模式。它是一种广播式的交换器,会将吸收到的消息发送给全部绑定到该交换器的队列,而不思量路由键(routing key)。这意味着无论消息发布时指定了什么路由键,Fanout 交换器都会忽略这些信息,并简单地将消息复制并分发给全部的绑定队列。
1.1 设置类
- @Configuration
- public class FanoutRabbitConfig {
- // 1. 声明注册fanout模式的交换机
- @Bean
- public FanoutExchange fanoutOrderExchange() {
- // return new DirectExchange("TestDirectExchange",true,true);
- return new FanoutExchange("fanout_order_exchange", true, false);
- }
- // 2. 申明队列sms.fanout.queue email.fanout.queue duanxin.fanout.queue
- @Bean
- public Queue fanoutEmailQueue() {
- // durable:是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效
- // exclusive:默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable
- // autoDelete:是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。
- // return new Queue("TestDirectQueue",true,true,false);
- //一般设置一下队列的持久化就好,其余两个就是默认false
- return new Queue("email.fanout.queue", true);
- }
- @Bean
- public Queue fanoutSmsQueue() {
- return new Queue("sms.fanout.queue", true);
- }
- @Bean
- public Queue fanoutWeixinQueue() {
- return new Queue("weixin.fanout.queue", true);
- }
- // 3. 完成绑定关系
- @Bean
- public Binding fanoutBindingDirect1() {
- return BindingBuilder.bind(fanoutEmailQueue()).to(fanoutOrderExchange());
- }
- @Bean
- public Binding fanoutBindingDirect2() {
- return BindingBuilder.bind(fanoutSmsQueue()).to(fanoutOrderExchange());
- }
- @Bean
- public Binding fanoutBindingDirect3() {
- return BindingBuilder.bind(fanoutWeixinQueue()).to(fanoutOrderExchange());
- }
- }
复制代码 1.2 生产者
- public void makeOrder(Long userId, Long productId, int num) {
- // 1: 模拟用户下单
- String orderNumer = UUID.randomUUID().toString();
- // 2: 根据商品id productId 去查询商品的库存
- // int numstore = productSerivce.getProductNum(productId);
- // 3:判断库存是否充足
- // if(num > numstore ){ return "商品库存不足..."; }
- // 4: 下单逻辑
- // orderService.saveOrder(order);
- // 5: 下单成功要扣减库存
- // 6: 下单完成以后
- System.out.println("用户 " + userId + ",订单编号是:" + orderNumer);
- // 发送订单信息给RabbitMQ fanout
- String exchangeName = "fanout_order_exchange";
- String routeKey = "";
- rabbitTemplate.convertAndSend(exchangeName, routeKey, orderNumer);
- }
复制代码 1.3 斲丧者
- // bindings其实就是用来确定队列和交换机绑定关系
- @RabbitListener(queues = {"email.fanout.queue"})
- @Component
- public class FanoutEmailService {
- // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
- @RabbitHandler
- public void messagerevice(String message){
- // 此处省略发邮件的逻辑
- System.out.println("fanout-email-------------->" + message);
- }
- }
复制代码- // bindings其实就是用来确定队列和交换机绑定关系
- @RabbitListener(queues = {"sms.fanout.queue"})
- @Component
- public class FanoutSMSService {
- // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
- @RabbitHandler
- public void messagerevice(String message){
- // 此处省略发邮件的逻辑
- System.out.println("fanout-sms-------------->" + message);
- }
- }
复制代码- @RabbitListener(queues = {"weixin.fanout.queue"})
- @Component
- public class FanoutWeixinService {
- // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
- @RabbitHandler
- public void messagerevice(String message){
- // 此处省略发邮件的逻辑
- System.out.println("fanout-weixin-------------->" + message);
- }
- }
复制代码 2. direct模式
Direct 交换器根据消息的路由键(routing key)和队列绑定时指定的路由键举行精确匹配来决定消息的分发。假如一个队列绑定了带有特定路由键的 Direct 交换器,那么只有当发布到该交换器的消息携带雷同的路由键时,消息才会被发送到这个队列。
2.1 设置类
留意设置类中声明的交换机的范例,以及队列携带的路由key- @Configuration
- public class DirectRabbitConfig {
- // 1. 声明注册fanout模式的交换机
- @Bean
- public DirectExchange directOrderExchange() {
- return new DirectExchange("direct_order_exchange", true, false);
- }
- // 2. 申明队列sms.fanout.queue email.fanout.queue duanxin.fanout.queue
- @Bean
- public Queue directEmailQueue() {
- // durable:是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效
- // exclusive:默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable
- // autoDelete:是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。
- // return new Queue("TestDirectQueue",true,true,false);
- //一般设置一下队列的持久化就好,其余两个就是默认false
- return new Queue("email.direct.queue", true);
- }
- @Bean
- public Queue directSmsQueue() {
- return new Queue("sms.direct.queue", true);
- }
- @Bean
- public Queue directWeixinQueue() {
- return new Queue("weixin.direct.queue", true);
- }
- // 3. 完成绑定关系
- @Bean
- public Binding directBindingDirect1() {
- return BindingBuilder.bind(directWeixinQueue()).to(directOrderExchange()).with("weixin");
- }
- @Bean
- public Binding directBindingDirect2() {
- return BindingBuilder.bind(directSmsQueue()).to(directOrderExchange()).with("sms");
- }
- @Bean
- public Binding directBindingDirect3() {
- return BindingBuilder.bind(directEmailQueue()).to(directOrderExchange()).with("email");
- }
- }
复制代码 2.2 生产者
- public void makeOrderDirect(Long userId, Long productId, int num) {
- // 1: 模拟用户下单
- String orderNumer = UUID.randomUUID().toString();
- // 2: 根据商品id productId 去查询商品的库存
- // int numstore = productSerivce.getProductNum(productId);
- // 3:判断库存是否充足
- // if(num > numstore ){ return "商品库存不足..."; }
- // 4: 下单逻辑
- // orderService.saveOrder(order);
- // 5: 下单成功要扣减库存
- // 6: 下单完成以后
- System.out.println("用户 " + userId + ",订单编号是:" + orderNumer);
- String exchangeName = "direct_order_exchange";
- rabbitTemplate.convertAndSend(exchangeName, "email", orderNumer);
- rabbitTemplate.convertAndSend(exchangeName, "weixin", orderNumer);
- }
复制代码 2.3 斲丧者
- // bindings其实就是用来确定队列和交换机绑定关系
- @RabbitListener(queues = {"email.direct.queue"})
- @Component
- public class DirectEmailService {
- // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
- @RabbitHandler
- public void messagerevice(String message){
- // 此处省略发邮件的逻辑
- System.out.println("direct-email-------------->" + message);
- }
- }
复制代码- // bindings其实就是用来确定队列和交换机绑定关系
- @RabbitListener(queues = {"sms.direct.queue"})
- @Component
- public class DirectSMSService {
- // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
- @RabbitHandler
- public void messagerevice(String message){
- // 此处省略发邮件的逻辑
- System.out.println("direct-sms-------------->" + message);
- }
- }
复制代码- @RabbitListener(queues = {"weixin.direct.queue"})
- @Component
- public class DirectWeixinService {
- // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
- @RabbitHandler
- public void messagerevice(String message){
- // 此处省略发邮件的逻辑
- System.out.println("direct-weixin-------------->" + message);
- }
- }
复制代码 3. topic模式
Topic 交换器是 RabbitMQ 中用于更机动的消息路由模式。它连合了 Direct 交换器的基于路由键匹配的特点,但允许利用通配符举行部门匹配。这使得 Topic 交换器非常适当于实现动态且复杂的路由逻辑。
3.1 设置类
无,采取注解的方式
3.2 生产者
- public void makeOrderTopic(Long userId, Long productId, int num) {
- // 1: 模拟用户下单
- String orderNumer = UUID.randomUUID().toString();
- // 2: 根据商品id productId 去查询商品的库存
- // int numstore = productSerivce.getProductNum(productId);
- // 3:判断库存是否充足
- // if(num > numstore ){ return "商品库存不足..."; }
- // 4: 下单逻辑
- // orderService.saveOrder(order);
- // 5: 下单成功要扣减库存
- // 6: 下单完成以后
- System.out.println("用户 " + userId + ",订单编号是:" + orderNumer);
- String exchangeName = "topic_order_exchange";
- // String routeKey = "jack.weixin.sss";
- String routeKey = "com.email.duanxin";
- rabbitTemplate.convertAndSend(exchangeName, routeKey, orderNumer);
- }
复制代码 3.3 斲丧者
- // bindings其实就是用来确定队列和交换机绑定关系
- @RabbitListener(bindings =@QueueBinding(
- // email.fanout.queue 是队列名字,这个名字你可以自定随便定义。
- value = @Queue(value = "email.topic.queue",autoDelete = "false"),
- // order.fanout 交换机的名字 必须和生产者保持一致
- exchange = @Exchange(value = "topic_order_exchange",
- // 这里是确定的rabbitmq模式是:fanout 是以广播模式 、 发布订阅模式
- type = ExchangeTypes.TOPIC),
- key = "#.email.#"
- ))
- @Component
- public class TopicEmailService {
- // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
- @RabbitHandler
- public void messagerevice(String message){
- // 此处省略发邮件的逻辑
- System.out.println("topic-email-------------->" + message);
- }
- }
复制代码- // bindings其实就是用来确定队列和交换机绑定关系
- @RabbitListener(bindings =@QueueBinding(
- // email.fanout.queue 是队列名字,这个名字你可以自定随便定义。
- value = @Queue(value = "sms.topic.queue",autoDelete = "false"),
- // order.fanout 交换机的名字 必须和生产者保持一致
- exchange = @Exchange(value = "topic_order_exchange",
- // 这里是确定的rabbitmq模式是:fanout 是以广播模式 、 发布订阅模式
- type = ExchangeTypes.TOPIC),
- key = "#.sms.#"
- ))
- @Component
- public class TopicSMSService {
- // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
- @RabbitHandler
- public void messagerevice(String message){
- // 此处省略发邮件的逻辑
- System.out.println("topic-sms-------------->" + message);
- }
- }
复制代码- @RabbitListener(bindings =@QueueBinding(
- // email.fanout.queue 是队列名字,这个名字你可以自定随便定义。
- value = @Queue(value = "weixin.topic.queue",autoDelete = "false"),
- // order.fanout 交换机的名字 必须和生产者保持一致
- exchange = @Exchange(value = "topic_order_exchange",
- // 这里是确定的rabbitmq模式是:fanout 是以广播模式 、 发布订阅模式
- type = ExchangeTypes.TOPIC),
- key = "#.weixin.#"
- ))
- @Component
- public class TopicWeixinService {
- // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
- @RabbitHandler
- public void messagerevice(String message){
- // 此处省略发邮件的逻辑
- System.out.println("topic-weixin-------------->" + message);
- }
- }
复制代码 4. 设置类VS注解
RabbitMQ 是一个开源的消息署理和队列服务器,用来实现应用步调之间的消息转达。在利用 RabbitMQ 时,设置类和注解是两种常见的设置方式。每种方式都有其长处和缺点。
4.1 设置类
- 机动性: 利用设置类可以非常机动地界说复杂的队列、交换器、绑定等。
- 可重用性: 设置类可以被多个组件或服务复用。
- 易于管理: 当项目变得复杂时,设置类可以让设置项更加会合,易于管理和维护。
- 明白性: 设置类使得设置逻辑清楚可见,便于明白业务逻辑。
- 测试友爱: 可以更容易地为设置类编写单位测试。
- 代码量: 相比于注解,设置类通常须要更多的代码来设置雷同的设置。
- 学习曲线: 对于初学者来说,大概须要一些时间来把握怎样精确利用设置类举行设置。
- 分散留意力: 开发者须要在业务逻辑和服务设置之间切换,大概会轻微分散对告急业务的关注。
4.2 注解
长处:
- 轻便: 利用注解可以直接在类或方法上声明设置,淘汰模板代码,使代码更轻便。
- 快速开发: 对于简单的应用场景,注解可以资助开发者快速完成设置,进步开发服从。
- 直观: 注解直接与干系的类或方法关联,使得设置意图一览无余。
- 集成精良: 在Spring框架中,注解方式可以很好地与Spring的其他功能(如AOP)连合利用。
缺点:
- 扩展性: 当需求变更或体系规模扩大时,注解大概不敷以应对复杂的设置需求。
- 隐式设置: 过多利用注解大概导致设置变得隐晦,不那么显而易见,这大概倒霉于后续的维护。
- 限定性: 注解提供的是预设好的设置选项,对于非尺度设置支持不敷机动。
- 调试困难: 假如出现设置错误,注解方式大概不容易定位题目所在。
|