生产者消费者模式/点到点模式/队列模式:
即生产者生产若干消息,由若干消费者共同消费消息,消息不重复消费。
发布订阅模式/主题模式:(pub/sub)
生产者生产若干消息,每个消费者都消费全部的消息。
独占消息模式:
只有一个消费者在消费消息,其他消费者干瞪眼,当消费者挂掉后才会由下一个消费者接着消费。
activemq简单写出生产者和消费者步骤:(发布订阅模式有代码例子)
生产者:
1.创建ConnectionFactory
2.创建Connection
3.启动连接
4.创建会话
5.创建一个目标
6.创建一个生产者
7.创建消息
8.发布消息
9.关闭连接
消费者:
1.创建连接工厂connectionfactory
2.创建连接
3.启动连接
4.创建会话
5.创建一个目标
6.创建一个消费者
7.创建一个监听器
activemq中的消息独占模式也是队列模式中的一种。
activemq消费模式中消息独占模式可以保证消息按照顺序消费,这种模式即使是在集群模式中,也只有一个节点在进行消息的消费,其他节点不进行消费,当正在消费的节点挂掉了,才会启用第二个节点进行消费,所以多节点中其他节点只能做备用,效率自然也就只有一个节点的效率了。
producer发送消息是有先后顺序的,这种顺序保持到了broker中。如果希望消息按顺序被消费掉,则应该把消息投送给单独一个consumer。如果队列只有一个consumer,那就很ok了,broker没有选择。但是,一旦唯一的consumer挂了,会造成服务不可用。因此出现了exclusive consumer,配置如下:
new ActiveMQQueue("TEST.QUEUENAME?consumer.exclusive=true");
也可以在监听注解那里加上:
@JmsListener(destination = "test.ruby.queue?consumer.exclusive=true")
如果有2个consumer都是这样配置的,broker只会把队列消息发送给其中一个consumer,如果这个consumer挂掉了,broker会把消息推送给另外的consumer,这样就保证了按顺序消费消息。
这种消息独占模式消费模式只有一个节点可以正常接收消息,其他节点只能作为备用,所以即使部署的是集群多节点消费者,实际上干活消费的只有一个消费者,自然效率和处理速度也就只有一个节点的效率和速度了。
源码解析:
https://www.cnblogs.com/allenwas3/p/8652484.html
https://blog.csdn.net/yaoqinggg/article/details/82563304
发布订阅模式:
生产者生产的消息会被每一个消费者消费一遍,即每个消费者都会消费生产者的所有消息。不过,消费者必须提前启动,启动后才可以消费此时生产者发送的消息,启动前的消息不消费,即消费者不能消费订阅之前就发送到主题中的消息。
代码例子:
消费者:
package com.mq.ruby.publishsubscribe;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
/**
* 主题模式
* 也是发布订阅模式
* 消费者
*/
public class AppConsumer {
private static final String url = "tcp://127.0.0.1:61616";
private static final String topicName = "topic-ceshi";
private static final String userName = "admin";
private static final String passWord = "admin";
public static void main(String[] args) throws Exception{
//1.创建连接工厂connectionfactory
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(userName, passWord, url);
//2.创建连接
Connection connection = activeMQConnectionFactory.createConnection();
//3.启动连接
connection.start();
//4.创建会话
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//5.创建一个目标
//队列模式
Destination queue = session.createQueue(topicName);
//主题模式
Destination topic = session.createTopic(topicName);
//6.创建一个消费者
MessageConsumer consumer = session.createConsumer(topic);
//7.创建一个监听器
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
try {
System.out.println("接收消息为:"+((TextMessage)message).getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
});
//8.关闭连接
// connection.close();
}
}
生产者:
package com.mq.ruby.publishsubscribe;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
/**
* 主题模式
* 也是发布订阅模式
* 生产者
*/
public class AppProducer {
private static final String url = "tcp://127.0.0.1:61616";
private static final String topicName = "topic-ceshi";
private static final String userName = "admin";
private static final String passWord = "admin";
public static void main(String[] args) throws Exception {
//1.创建ConnectionFactory
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(userName,passWord,url);
//2.创建Connection
Connection connection = connectionFactory.createConnection();
//3.启动连接
connection.start();
//4.创建会话
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//5.创建一个目标
//队列模式
Destination queue = session.createQueue(topicName);
//主题模式
Destination destination = session.createTopic(topicName);
//6.创建一个生产者
MessageProducer producer = session.createProducer(destination);
for (int i = 0; i<10; i++) {
//7.创建消息
TextMessage textMessage = session.createTextMessage("test" + i);
//8.发布消息
producer.send(textMessage);
System.out.println("生产者发送消息:"+textMessage.getText());
}
//9.关闭连接
connection.close();
}
}
感觉写的有点乱糟糟的,谢谢大家评论指出不足