1. 对比Direct模式和Topic模式
Direct模式和Topic模式都属于条件匹配
, 满足routingKey匹配条件的栈都会接收到消息. 但是Topic更为强大, 相比于Direct直接匹配Topic则是模糊匹配
, 提供了两种模糊匹配符.
#
匹配任意个单词*
匹配一个单词
Direct模式模型:
Topic模式模型:
2. 编码实现Topic模式
2.1 生产者模块代码
模拟登陆服务:
@Service
public class LoginService {
@Resource
private RabbitTemplate rabbitTemplate;
/**
* Topic模式注解实现 将登陆功能进行解耦
* @param phone
* @param userInfo
*/
public void login(String phone, String userInfo) {
// 1. 模拟用户入库
System.out.println(phone+" 用户注册"+" 信息为"+userInfo);
// 2. 作为生产者向队列中发送消息
String exchangeName = "login_topic_exchange";
// topic模式模糊匹配规则
// # 0或多个单词, * 一个单词
String routingKey = "sand.sms";
rabbitTemplate.convertAndSend(exchangeName, routingKey, userInfo);
}
}
测试登陆服务, 发送消息:
@SpringBootTest
class ProducerServerApplicationTests {
@Resource
private LoginService loginService;
@Test
void contextLoads() {
loginService.login("120", "用户信息");
}
}
运行测试发送消息:
2.2 消费者模块代码(注解实现交换机和队列的绑定)
邮件服务消费者:
@Service
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(value = "login_topic_exchange", type = ExchangeTypes.TOPIC),
value = @Queue(value = "mail.topic.queue",durable = "true", autoDelete = "false"),
key = "#.mail.#" // 匹配规则, 满足规则的栈都会受到交换机发来的消息
))
public class MailConsumerService {
@RabbitHandler
public void sandMail(String message) {
System.out.println("mail接收到消息: "+ message + " 进行发送");
}
}
短信服务消费者:
@Service
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(value = "login_topic_exchange", type = ExchangeTypes.TOPIC),
value = @Queue(value = "sms.topic.queue",durable = "true", autoDelete = "false"),
key = "#.sms.#"
))
public class SMSConsumerService {
@RabbitHandler
public void sandSMS(String message) {
System.out.println("sms接收到消息: "+ message + " 进行发送");
}
}
启动消费者模块, 测试消息消费:
3. 总结
使用topic模式我们更加灵活的向指定队列中发送消息. 也能让我们的系统扩展性更为强大, 当配置好一定的匹配规则我们就能从消费者端横向异步扩容我们的服务.