MQ的作用
削峰:如秒杀业务在某一段时间访问量剧增,导致服务器压力过大。使用了MQ后,服务接收到请求发送到mq,然后直接结束。
解耦:A服务需要调用B和C服务,哪天新增了D服务,则A服务还需要改动,这样很麻烦。使用MQ,则A服务只需要把请求发给MQ, BCD服务订阅A服务的请求即可。
异步:A需要调用B、C、D服务都是50毫秒, 但B调B1需要2秒,最后A的调用时间也超过了2秒。使用MQ则A发请求给MQ然后就结束了,返回时间50毫秒左右。
消息消费方式
阻塞式:MessageConsumer.receive() 方法阻塞接收,receive方法在能接收到消息之前(或超时之前)将一直阻塞。
MessageConsumer consumer = session.createConsumer(queue);
while (true) {
// reveive() 一直等待接收消息,在能够接收到消息之前将一直阻塞。是同步阻塞方式 。
TextMessage textMessage = (TextMessage) consumer.receive();
if (textMessage != null) {
System.out.println("消费者收到的消息:" + textMessage.getText());
} else {
break;
}
}
异步非阻塞方式:MessageConsumer.setMessageListener()监听,当消息到达之后,系统会自动调用监听器MessageListener的onMessage(Message message)方法。
MessageConsumer consumer = session.createConsumer(queue);
/* 通过监听的方式来消费消息,是异步非阻塞的方式消费消息。
通过messageConsumer 的setMessageListener 注册一个监听器,当有消息发送来时,系统自动调用MessageListener 的 onMessage 方法处理消息
*/
consumer.setMessageListener(new javax.jms.MessageListener() {
public void onMessage(Message message) {
// instanceof 判断是否A对象是否是B类的子类
if (message != null && message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("消费者的消息:" + textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
});
Queue队列消息传递特点
1. 消息生产者和消费者一对一
2. 生产者和消费者无关联,生产者生产完消息发给mq即可,不需要关注消息是否消费。消费者有消息直接消费即可,不需要关注生产者是否正常。
3. 消息消费后不再存储
Topic发布订阅消息
1. 生产者和订阅者是1对N的关系
2. 生产者和订阅者是有强关联的,订阅者不能订阅开启之前的消息。
3. 生产者生产的消息如果没有订阅者,将是一条废弃的消息。所以一般打开订阅者再开始生产消息。
Queue和Topic区别