四种类型
Direct: 消息中的路由键(routing key)如果和 Binding 中的 binding key 一致,交换器就将消息发到对应的队列中。它是完全匹配、单播的模式。
Fanout: 每个发到 fanout 类型交换器的消息都会分到所有绑定的队列上去。很像子网广播,每台子网内的主机都获得了一份复制的消息。fanout 类型转发消息是最快的
topic: topic 交换器通过模式匹配分配消息的路由键属性,将路由键和某个模式进行匹配,此时队列需要绑定到一个模式上。它将路由键和绑定键的字符串切分成单词,这些单词之间用点隔开。它同样也会识别两个通配符:符号“#” 和符号“” 。 “#” 匹配 0 个或多个单词,“”匹配不多不少一个单词
Headers: 不处理路由键。而是根据发送的消息内容中的headers属性进行匹配。在绑定Queue与Exchange时指定一组键值对;当消息发送到RabbitMQ时会取到该消息的headers与Exchange绑定时指定的键值对进行匹配;如果完全匹配则消息会路由到该队列,否则不会路由到该队列。headers属性是一个键值对,可以是Hashtable,键值对的值可以是任何类型。而fanout,direct,topic 的路由键都需要要字符串形式的。
匹配规则x-match有下列两种类型:
-
x-match = all :表示所有的键值对都匹配才能接受到消息
-
x-match = any :表示只要有键值对匹配就能接受到消息
项目里怎么用的(以topic为例)
RabbitMQConfig:
@Configuration
public class RabbitMQTopicConfig {
private static final String QUEUE="seckillQueue";
private static final String EXCHANGE="seckillExchange";
@Bean
public Queue queue(){
return new Queue(QUEUE);
}
@Bean
public TopicExchange topicExchange(){
return new TopicExchange(EXCHANGE);
}
@Bean
public Binding binding(){
return BindingBuilder.bind(queue()).to(topicExchange()).with("seckill.#");
}
}
MQSender:
@Service
@Slf4j
public class MQSender {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendSeckillMessage(String msg){
log.info("发送消息"+msg);
rabbitTemplate.convertAndSend("seckillExchange","seckill.message",msg);
}
}
MQReceiver:
@Service
@Slf4j
public class MQReceiver {
@Autowired
private IGoodsService goodsService;
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private IOrderService orderService;
@RabbitListener(queues="seckillQueue")
public void receive(String msg){
log.info("接收消息"+msg);
SeckillMessage seckillMessage = JsonUtil.jsonStr2Object(msg, SeckillMessage.class);
Long goodsId=seckillMessage.getGoodsId();
User user = seckillMessage.getUser();
//判断库存
GoodsVo goodsVo = goodsService.findGoodsVoByGoodsId(goodsId);
if(goodsVo.getStockCount()<1){
return;
}
//判断是否重复抢购
SeckillOrder seckillOrder =(SeckillOrder) redisTemplate.opsForValue().get("order:"+user.getId()+":"+goodsId);
if (seckillOrder != null) {
return;
}
orderService.seckill(user,goodsVo);
}
}