写在前面:
终于终于学到了ActiveMQ,和之前的Nginx一样。对ActiveMQ也保持着极高的兴趣。听说过没用过,学完Nginx就开始了ActiveMQ。
一、安装
①官网下载Linux版
②tar–zxcf apache-activemq-5.15.13-bin.tar.gz到/opt目录下
③复制到根目录 /mycativeMQ。cp –r apache-activemq-5.15.13/myactiveMQ
二、启动
在bin目录下。
启动 ./activemq start带运行日志启动./activemq start > /myactiveMQ/run_activemq.log
关闭 ./activemq stop
重载 ./activemq reload
默认后台端口 6161
默认前台(管理控制台)端口 8161默认用户名/密码 admin/admin
*查看后台进程的3种方式
ps–ef | grep activemq | grep –v grep
netstat–anp | grep 61616
lsof–i:61616
三、JMS开发的基本步骤
生产者-队列
public class JmsProduce {
private static final String ACTIVEMQ_URL = "tcp://192.168.91.130:61616";
private static final String QUEUE_NAME = "queue01";
public static void main(String[] args) throws JMSException {
//1.创建连接工厂。按照给定的url地址,采用默认用户名和密码
ActiveMQConnectionFactory activeMQConnection = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
//2.通过连接工厂,获得连接connection并启动访问
Connection connection = activeMQConnection.createConnection();
connection.start();
//3.创建会话Session
//有两个参数 第一个叫事务、第二个叫签收
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//4.创建目的地(具体是队列还是主题topic)
Queue queue = session.createQueue(QUEUE_NAME); //Collections collection = new ArrayList() == Destination destination = session.createQueue(QUEUE_NAME);
//5.创建消息的生产者
MessageProducer messageProducer = session.createProducer(queue);
//6.通过使用messageProducer生产3条消息发送到MQ的队列里
for (int i = 0; i < 3; i++) {
//7.创建消息
TextMessage textMessage = session.createTextMessage("msg----" + i);
//8.通过messageProducer发送给MQ
messageProducer.send(textMessage);
}
//9.关闭资源
messageProducer.close();
session.close();
connection.close();
System.out.println("***********消息发布到MQ完成");
}
}
消费者-队列-消费方式1 receive()
MessageConsumer messageConsumer = session.createConsumer(queue);
//同步阻塞式 receive()来消费消息
while (true){
TextMessage textMessage = (TextMessage)messageConsumer.receive(5000L);
if(null != textMessage){
System.out.println("*********消费者接收到消息:"+textMessage.getText());
}else {
break;
}
}
messageConsumer.close();
session.close();
connection.close();
消费者-队列-消费方式2(listener)
MessageConsumer messageConsumer = session.createConsumer(queue);
//异步非阻塞式 通过监听的方式来消费消息
messageConsumer.setMessageListener(new MessageListener() {
public void onMessage(Message message) {
if(null != message && message instanceof TextMessage){
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("*********消费者接收到消息:"+textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
});
System.in.read(); //保证控制台灯不灭
messageConsumer.close();
session.close();
connection.close();
*消费顺序-队列
先创造2个消费者。再生产4条消息。
每个消费者轮询的获取每条消息。
目的地
在点对点的消息传递域中,目的地被称为队列(queue)
在发布订阅消息传递域中,目的地被称为主题(topic)
先消费(订阅)再生产(发布)
生产者-主题
其余和生产者-队列的保持一致。唯独创建目的地
Topic topic = session.createTopic("topic01");
消费者-主题
其余和消费者-队列的保持一致。唯独创建目的地
Topic topic = session.createTopic("topic01");
MessageConsumer messageConsumer = session.createConsumer(topic);
messageConsumer.setMessageListener((message)->{
if(null != message && message instanceof TextMessage){
TextMessage textMessage = (TextMessage)message;
try {
System.out.println("*********Topic消费者接收到消息:"+textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
});
先消费(订阅)再生产(发布).
队列VS主题
队列 | 主题 |
“负载均衡”模式。 | “订阅-发布“模式。 |
即使没有消费者,消息也不会丢弃。 | 没有消费者,消息会丢弃 |
一条消息对应一个消费者。 | 有多个订阅者,每个订阅者都会收到消息。 |
四、JMS的组成结构和特点
JMS(Java Message Server)主要由消息头、消息体、消息属性组成。
消息头
①setJMSDestination(Destination destination)设置目的地
②setDeliveryMode(DeliveryMode.PERSISTENT);设置持久模式
DeliveryMode.PERSISTENT:JMS发送出现故障,该消息不会消失,服务恢复之后再次传递。
DeliveryMode.NON_PERSISTENT:最多传递一次,意味着服务出现故障,消息永远丢失。
③ setJMSExpiration(long tinmeToLive)设置消息过期时间
④ setJMSPriority(int)设置优先级
从0-9十个级别,0-4普通级别,5-9加急消息。默认4级,加急消息优先于普通消息。
⑤ setJMSMessageID()设置消息ID
唯一标识每个消息的标识,由MQ产生。
消息体
TextMessage textMessage1 = session.createTextMessage();
textMessage1.setText("String s");
MapMessage mapMessage1 = session.createMapMessage();
mapMessage1.setString("k1","v1");
session.createBytesMessage();
session.createObjectMessage();
session.createStreamMessage();
消息属性
去重、标识、重点标注(对消息头的补充)
textMessage.setStringProperty("property_name","property_value");
textMessage.getStringProperty("property_name");
五、JMS的可靠性
可靠性(持久性、事务、签收)
持久性
队列:
默认持久化messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT);
DeliveryMode.PERSISTENT:JMS发送出现故障,该消息不会消失,服务恢复之后再次传递。
DeliveryMode.NON_PERSISTENT:最多传递一次,意味着服务出现故障,消息永远丢失。
主题:
connection.setClientID("z4"); //向MQ注册一个自己身份ID识别号
TopicSubscriber topicSubscriber = session.createDurableSubscriber(topic, "备注");//创造持久化订阅者
一定要先运行一次消费者(等于向MQ注册)。 然后再运行生产者发送消息。 此时,无论消费者是否在线,都会接收到。如果不在线,下次连接时会把没有接收到的消息接收下来。 |
事务(偏生产者)
//有两个参数 第一个叫事务、第二个叫签收
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
开启事务:
connection.createSession(true,Session.AUTO_ACKNOWLEDGE);
session.commit();//提交事务
session.rollback();//回滚
消费者:开启了事务也要commit()避免消息重复消费。
签收(偏消费者)
自动签收(默认)Session.AUTO_ACKNOWLEDGE
手动签收Session.CLIENT_ACKNOWLEDGE
没开启事务(手动签收)
connection.createSession(false,Session.CLIENT_ACKNOWLEDGE)
textMessage.acknowledge();//手动签收
事务VS签收 开启事务:当一个事务被成功提交则消息被自动签收。如果事务回滚,则消息被再次传送。 关闭事务:消息何时被确认,取决于创建会话时的应答模式(acknowledge |
六、JMS点对点总结
①点对点模型是基于队列的。生产者发送消息到队列,消费者从队列接收到消息。实现了“异步传输”。
②如果Session关闭时,有部分消息已被收到但还没签收acknowledged那当消费者下次连接到相同队列时,消息还会被再次接收(消息重复)
③队列可以长久保存消息直到消费者收到消息。消费者不用担心,消息会丢失而时刻和队列保持激活的连接状态。
七、JMS发布、订阅总结
①主题被认为是消息的传输中介,发布者publisher发布消息到主题,订阅者subscribler从主题订阅消息。
②主题使得消息订阅者和消息发布者保持互相独立,不需要接触即可消息传达。
未完待续。。。