ActiveMQ学习笔记(上)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/boyish_/article/details/51734525


公司做智能硬件的,使用ActiveMQ做消息队列,我接手这块,学习了一下,记点笔记,供大家参考


一、ActiveMQ简介

ActiveMQ,名字上看是一种MessageQueue,其实是支持Queue(队列)和Topic(广播)两种模式。

他本身是一种异步的处理机制,所以主要的应用场景主要是对大应用解耦合,做异步处理,他所支持的mqtt协议还可以用作移动端与服务器的通讯处理。

ActiveMQ是支持JMS规范的,我们知道JMS有两种消息模型(Point-to-Point(点对点)和Publish/Subscribe Message(消息广播)),虽然他们的父类都可以实现Queue和Topic,但是基于规范,建议基于p2p模型实现Queue模式,基于Pub/Sub实现Topic。


二、Queue消息

Queue是点对点的消息模型,一个Sender虽然可以有多个Receiver,但是Sender发出的消息只会由一个并且是保证有且只有一个Receiver接收,接收后mq会收到通知把这条消息删除,如果暂时没有Receiver,Queue默认在mq服务器上以文件形式保存,直到有一个Receiver连线接收。

1.Queue发送

            // 创建链接工厂
            QueueConnectionFactory factory = new ActiveMQConnectionFactory(null, null, "tcp://127.0.0.1:61616");
            // 通过工厂创建一个连接
            connection = factory.createQueueConnection();
            // 启动连接
            connection.start();
            // 创建一个session会话
            session = connection.createQueueSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);//①
            // 创建一个消息队列
            Queue queue = session.createQueue("test.queue");
            // 创建消息发送者
            javax.jms.QueueSender sender = session.createSender(queue);
            // 设置持久化模式
            sender.setDeliveryMode(DeliveryMode.PERSISTENT);//②
            MapMessage map = session.createMapMessage();
            map.setString("text", message);       
            sender.send(map);
            // 提交会话
            session.commit();


2.Queue接收

	     // 创建链接工厂
            QueueConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER,
					ActiveMQConnection.DEFAULT_PASSWORD, "tcp://127.0.0.1:61616");
            // 通过工厂创建一个连接
            connection = factory.createQueueConnection();
            // 启动连接
            connection.start();
            // 创建一个session会话
            session = connection.createQueueSession(Boolean.FALSE, Session.CLIENT_ACKNOWLEDGE);//①
            // 创建一个消息队列
            Queue queue = session.createQueue("test.queue");
            // 创建消息制作者
            javax.jms.QueueReceiver receiver = session.createReceiver(queue);
            
            receiver.setMessageListener(new MessageListener() {
                public void onMessage(Message msg) { 
                    if (msg != null) {
                        MapMessage map = (MapMessage) msg;
                        try {
                            System.out.println(map.getLong("time") + "接收#" + map.getString("text"));
                            msg.acknowledge();//③
                        } catch (JMSException e) {
                            e.printStackTrace();
                        }
                    }
                } 
            }); 
            // 提交会话
            session.commit();


①connection.createQueueSession(A, B):

如果A为true,为支持事务,则B只能为SESSION_TRANSACTED,这种情况下,在事务开启之后,和session.commit()之前,所有消费的消息,要么全部正常确认,要么全部redelivery,由于Session是共享的,使用此种方式时,需要对每一个请求创建新的session,以为造成业务处理错误;

如果A为false,则不支持事务则,B可以为AUTO_ACKNOWLEDGE、CLIENT_ACKNOWLEDGE或DUPS_OK_ACKNOWLEDGE。AUTO_ACKNOWLEDGE为自动确认(择机确认具有不确定性);CLIENT_ACKNOWLEDGE为客户端手动确认,如Queue接收实例中的③,该确认有两种方式,message.acknowledge()将当前session中所有consumer中尚未ACK的消息都一起确认,而ActiveMQMessageConsumer.acknowledege()只会对当前consumer中那些尚未确认的消息进行确认;DUPS_OK_ACKNOWLEDGE只对Topic消息起作用,当consumer故障重启后,那些尚未被MQ确认的消息会重新发送过来;

②queue消息未被消费或者手动清除的情况下是会保存的,在P2P类型中当DeliveryMode设置为NON_PERSISTENCE时,消息被保存在内存中,而当DeliveryMode设置为PERSISTENCE时,消息保存在broker的相应的文件或者数据库中。而且P2P中消息一旦被Consumer消费就从broker中删除。

MessageListener是异步模式,B不能为SESSION_TRANSACTED。


三、Topic消息

Topic是Publish-Subscribe-Message的消息模型,数据是无状态不落地的,所以publisher发出的每条消息不能保证subscriber都能收到,只有监听该publisher的subscriber才能收到,如果没有customer在监听,该消息就相当于消失了,Topic是一对多的,所有监听publisher的subscriber都可以收到消息。

1.Topic发送

	ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(null, null, "failover:(tcp://127.0.0.1:61616,tcp://127.0.0.1:61617,tcp://127.0.0.1:61618)");//①
    	
    	TopicConnection connection = factory.createTopicConnection();  
        connection.start();  
        TopicSession session = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
        
        TopicPublisher producer = session.createPublisher(new ActiveMQTopic("test.topic"));
        
	TextMessage message = session.createTextMessage();
	message.setText("message_" + System.currentTimeMillis());
	producer.send(message);
	session.commit();



2.Topic接收

	ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER,
				ActiveMQConnection.DEFAULT_PASSWORD, "failover:(tcp://127.0.0.1:61616,tcp://127.0.0.1:61617,tcp://127.0.0.1:61618)");
	TopicConnection connection = factory.createTopicConnection();  
	connection.start();  
	TopicSession session = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
	Topic topic = session.createTopic("test.topic");  
	TopicSubscriber consumer = session.createSubscriber(topic);     
	consumer.setMessageListener(new MessageListener() {  
	public void onMessage(Message message) {  
		ActiveMQBytesMessage tm = (ActiveMQBytesMessage) message;  
			System.out.println("Received message: " + tm.getMessage());   
		}  
	});
	session.commit();


①ActiveMQ支持断线重连

后记:先写到这儿,写一写对自己来说也收获颇多,下一篇涉及到mqtt的内容


展开阅读全文

没有更多推荐了,返回首页