ActiveMQ 总结
来源:互联网 发布:二级c语言选择题题库 编辑:程序博客网 时间:2024/05/17 07:08
ActiveMQ入门
http://www.cnblogs.com/zhuxiaojie/p/5564187.html
1JMS
1.1JMS规范
连接工厂:连接工厂是客户用来创建连接的对象。
连接:封装了客户与JMS提供者之间的一个虚拟连接。
会话:生产和消费消息的一个单线程上下文。
目的地:客户用来指定生产消息的目标,和消费消息的数据来源。
消息生产者:由会话创建的一个对象,用于把消息发送到一个目的地。
消息发送者:由会话创建的一个对象,用于接收发送到目的地的对象。
消息:消息包含了消息头,消息属性,消息体。
1.2JMS的可靠性
ACK机制:只有在被确认之后,才能被认为成功的消费了。
持久性:ActiveMQ的持久性可以用,data logs,kaha ,jdbc
消息过期:
临时目的地:
持久订阅:
本地事物:
2.ActiveMQ
2.1ActiveMQ的通讯方式
2.2 ActiveMQ特色
2.2.1 独占消费
queue中的消息是按照顺序被分发到consumers中的,而独占消费就是在很多consumer种只选择一个consumer来处理queue中的所有消息。
2.2.2 消息分组
独占消费的增强,也就是保证了消息属性相同的JMSGroup ID的消息会发送到相同的consumer
2.2.3 JMS selectors
消息过滤器,基于SQL语法。
2.2.4 Pending Message Limit Strategy
首先简要介绍一下prefetch机制。ActiveMQ通过prefetch机制来提高性能,这意味这客户端的内存里可能会缓存一定数量的消息。缓存消息的数量由prefetch limit来控制。当某个
consumer的prefetch buffer已经达到上限,那么broker不会再向consumer分发消息,直到consumer向broker发送消息的确认。
慢消费者会在非持久的topics上导致问题:一旦消息积压起来,会导致broker把大量消息保存在内存中,broker也会因此而变慢。未来ActiveMQ可能会实现磁盘缓存,但是这也还
是会存在性能问题。目前ActiveMQ使用Pending Message Limit Strategy来解决这个问题。除了prefetch buffer之外,你还要配置缓存消息的上限,超过这个上限后,新消息到
来时会丢弃旧消息。通过在配置文件的destination map中配置PendingMessageLimitStrategy,可以为不用的topic namespace配置不同的策略。目前有以下两种: • ConstantP
endingMessageLimitStrategy。这个策略使用常量限制。 例如:<constantPendingMessageLimitStrategy limit="50"/> • PrefetchRatePendingMessageLimitStrategy。这个
策略使用prefetch size的倍数限制。 例如:<prefetchRatePendingMessageLimitStrategy multiplier="2.5"/> 在以上两种方式中,如果设置0意味着除了prefetch之外不再缓存消
息;如果设置-1意味着禁止丢弃消息。 此外,你还可以配置消息的丢弃策略,目前有以下两种: • oldestMessageEvictionStrategy。这个策略丢弃最旧的消息。 • oldestMessag
eWithLowestPriorityEvictionStrategy。这个策略丢弃最旧的,而且具有最低优先级的消息。
2.2.5 虚拟队列
topic模式的增强。
它允许用一个虚拟的destination 代表多个destinations。例如你可以通过composite destinations在一个操作中同时向12个queue发送消息。
2.2.6 镜像队列
每个queue中的消息只能被一个consumer消费。然而,有时候你可能希望能够监视生产者和消费者之间的消息流。你可以通过使用Virtual Destinations 来建立一个virtual queue 来把消息转发到多个queues中。但是 为系统中每个queue都进行如此的配置可能会很麻烦。 ActiveMQ支持Mirrored Queues。Broker会把发送到某个que
ue的所有消息转发到一个名称类似的topic,因此监控程序可以订阅这个mirrored queue topic。为了启用Mirrored Queues,首先要将BrokerService的useMirroredQue
ues属性设置成true,然后可以通过destinationInterceptors设置其它属性,如mirror topic的前缀,缺省是"VirtualTopic.Mirror."。
2.2.7 支持同步异步发送2.2.8 分发策略
2.2.9 消息的游标
http://blog.csdn.net/neareast/article/details/7582947
2.2.10 批量确认
------------个人测试代码
package com.czy.demo.ActiveDemo.helloworld;import javax.jms.Connection;import javax.jms.ConnectionFactory;import javax.jms.Destination;import javax.jms.JMSException;import javax.jms.MessageConsumer;import javax.jms.Session;import javax.jms.TextMessage;import javax.jms.Topic;import org.apache.activemq.ActiveMQConnectionFactory;import org.junit.After;import org.junit.Before;import org.junit.Test;public class Receiver {Connection connection = null;Session session = null;MessageConsumer consumer = null;@Beforepublic void before() throws JMSException {// 1.创建ConnectionFactory工厂ConnectionFactory factory = new ActiveMQConnectionFactory("czy", "czy", "tcp://localhost:61616");// 2.创建Connectionconnection = factory.createConnection();connection.setClientID("11");// 持久化订阅要设置ID, //生产者创建的消息类型必须为持久化的connection.start();}@Testpublic void testQueue() throws JMSException {// 3.创建section// 第一个参数,是否开启事物 第二个参数 ACK的类型session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);// 4.创建destinationDestination destination = session.createQueue("queue1");consumer = session.createConsumer(destination);receive();/* * 分别运行receive和receive2的testQueue方法 发现俩个ActiveMQ会把队列中的消息依次发送给消费者,直到发送完毕 * 可能出现的结果 receive接受到消息0,2,4 receive2接受到结果1,3 */}@Testpublic void testTopic() throws JMSException {// 3.创建sectionsession = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);// 4.创建destinationDestination destination = session.createTopic("topic1");consumer = session.createConsumer(destination);receive();/* * 分别运行receive和receive2的testTopic方法 发现俩个ActiveMQ会把队列中的消息都发送给激活状态下的消费者 * 出现的结果 receive接受到消息0,1,2,3,4 receive2接受到结果0,1,2,3,4 * 如果消费者后运行,先运行生产者,消费者是接受不到消费的 */}@Testpublic void testAckNowledge() throws JMSException {// 3.创建section// Session.AUTO_ACKNOWLEDGE 自动提交// Session.CLIENT_ACKNOWLEDGE 客户端手动确认// Session.DUPS_OK_ACKNOWLEDGE 自动批量提交// Session.SESSION_TRANSACTED 在事物的环境中 这种ACK类型,前面的参数要为truesession = connection.createSession(Boolean.FALSE, Session.CLIENT_ACKNOWLEDGE);// ssession=connection.createSession(Boolean.TRUE,// Session.SESSION_TRANSACTED);// 4.创建destinationDestination destination = session.createQueue("queue1");consumer = session.createConsumer(destination);// receiveWithACK(false);// receiveWithACK(true);// receiveWithTransaction(null);// receiveWithTransaction(false);// receiveWithTransaction(true);/* * 分别先用前三章种ACK类型,创建session,然后运行receiveWithACK 发现自动提交和自动批量提交,表现一致, * 都是无论是否手动ACK,接受到的消息都会从未消费队列中删除 而手动提交只有提交之后才会在未消费队列中删除 * 用事物类型Ack创建session,然后运行receiveWithTransaction,只有显示提交才会从未消费队列中删除 * 回滚,或者不处理事物都不会从未消费队列中删除 */}@Testpublic void testDurableSubscriber() throws JMSException {// 3.创建sessionsession = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);// ssession=connection.createSession(Boolean.TRUE, Session.SESSION_TRANSACTED);// 4.创建destinationTopic topic = session.createTopic("topic1");consumer = session.createDurableSubscriber(topic, "11");receive();//先运行生产者生产消息,在运行消费者仍然可以接受到消费者离线前的消息//而且如果是客户端,手动ACK,俩个持久化的订阅不会相互影响//比如11,手动确认了,22仍然可以接受到消息,直到22也手动确认,事物也是一样}@Testpublic void testExclusive() throws JMSException{session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);Destination destination = session.createQueue("queue1?consumer.exclusive=true");consumer = session.createConsumer(destination);receive();/** * 测试结果,会从多个consumers中挑选一个consumer来处理queue中所有的消息, * 从而保证了消息的有序处理,而不是分发到各个消费者 */}@Testpublic void testSelecor() throws JMSException{// 3.创建section// 第一个参数,是否开启事物 第二个参数 ACK的类型session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);// 4.创建destinationDestination destination = session.createQueue("queue1");consumer = session.createConsumer(destination,"number>=2");receive();/** * 选择器,只会选择符合条件的消息, * 制定注意的是表达式中的属性不会进行自动类型转换 */}public void receiveWithTransaction(Boolean isCommit) throws JMSException {receive(null, isCommit);}public void receiveWithACK(Boolean isAck) throws JMSException {receive(isAck, null);}public void receive() throws JMSException {receive(null, null);}public void receive(Boolean isAck, Boolean isCommit) throws JMSException {// 6.消费消息内容while (true) {TextMessage message = (TextMessage) consumer.receive();System.out.println("");if (message == null)break;System.out.println("接受的内容" + message.getText());if (isAck!=null && isAck == true) {message.acknowledge();}if (isCommit == null) {} else if (isCommit == true) {session.commit();} else if (isCommit == false) {session.rollback();}}}@Afterpublic void close() throws JMSException {if (connection != null) {connection.close();}}}
package com.czy.demo.ActiveDemo.helloworld;import javax.jms.Connection;import javax.jms.ConnectionFactory;import javax.jms.Destination;import javax.jms.JMSException;import javax.jms.MessageConsumer;import javax.jms.Session;import javax.jms.TextMessage;import javax.jms.Topic;import org.apache.activemq.ActiveMQConnectionFactory;import org.junit.After;import org.junit.Before;import org.junit.Test;public class Receiver2 {Connection connection = null;Session session = null;MessageConsumer consumer = null;@Beforepublic void before() throws JMSException {// 1.创建ConnectionFactory工厂ConnectionFactory factory = new ActiveMQConnectionFactory("czy", "czy", "tcp://localhost:61616");// 2.创建Connectionconnection = factory.createConnection();connection.setClientID("22");// 持久化订阅要设置ID, //生产者创建的消息类型必须为持久化的connection.start();}@Testpublic void testQueue() throws JMSException {// 3.创建section// 第一个参数,是否开启事物 第二个参数 ACK的类型session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);// 4.创建destinationDestination destination = session.createQueue("queue1");consumer = session.createConsumer(destination);receive();/* * 分别运行receive和receive2的testQueue方法 发现俩个ActiveMQ会把队列中的消息依次发送给消费者,直到发送完毕 * 可能出现的结果 receive接受到消息0,2,4 receive2接受到结果1,3 */}@Testpublic void testTopic() throws JMSException {// 3.创建sectionsession = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);// 4.创建destinationDestination destination = session.createTopic("topic1");consumer = session.createConsumer(destination);receive();/* * 分别运行receive和receive2的testTopic方法 发现俩个ActiveMQ会把队列中的消息都发送给激活状态下的消费者 * 出现的结果 receive接受到消息0,1,2,3,4 receive2接受到结果0,1,2,3,4 * 如果消费者后运行,先运行生产者,消费者是接受不到消费的 */}@Testpublic void testAckNowledge() throws JMSException {// 3.创建section// Session.AUTO_ACKNOWLEDGE 自动提交// Session.CLIENT_ACKNOWLEDGE 客户端手动确认// Session.DUPS_OK_ACKNOWLEDGE 自动批量提交// Session.SESSION_TRANSACTED 在事物的环境中 这种ACK类型,前面的参数要为truesession = connection.createSession(Boolean.FALSE, Session.CLIENT_ACKNOWLEDGE);// ssession=connection.createSession(Boolean.TRUE,// Session.SESSION_TRANSACTED);// 4.创建destinationDestination destination = session.createQueue("queue1");consumer = session.createConsumer(destination);// receiveWithACK(false);// receiveWithACK(true);// receiveWithTransaction(null);// receiveWithTransaction(false);// receiveWithTransaction(true);/* * 分别先用前三章种ACK类型,创建session,然后运行receiveWithACK 发现自动提交和自动批量提交,表现一致, * 都是无论是否手动ACK,接受到的消息都会从未消费队列中删除 而手动提交只有提交之后才会在未消费队列中删除 * 用事物类型Ack创建session,然后运行receiveWithTransaction,只有显示提交才会从未消费队列中删除 * 回滚,或者不处理事物都不会从未消费队列中删除 */}@Testpublic void testExclusive() throws JMSException{session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);Destination destination = session.createQueue("queue1?consumer.exclusive=true");consumer = session.createConsumer(destination);receive();}@Testpublic void testDurableSubscriber() throws JMSException {// 3.创建sessionsession = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);// ssession=connection.createSession(Boolean.TRUE, Session.SESSION_TRANSACTED);// 4.创建destinationTopic topic = session.createTopic("topic1");consumer = session.createDurableSubscriber(topic, "22");receive();//先运行生产者生产消息,在运行消费者仍然可以接受到消费者离线前的消息//而且如果是客户端,手动ACK,俩个持久化的订阅不会相互影响//比如11,手动确认了,22仍然可以接受到消息,直到22也手动确认,事物也是一样}public void receiveWithTransaction(Boolean isCommit) throws JMSException {receive(null, isCommit);}public void receiveWithACK(Boolean isAck) throws JMSException {receive(isAck, null);}public void receive() throws JMSException {receive(null, null);}public void receive(Boolean isAck, Boolean isCommit) throws JMSException {// 6.消费消息内容while (true) {TextMessage message = (TextMessage) consumer.receive();System.out.println("");if (message == null)break;System.out.println("接受的内容" + message.getText());if (isAck!=null && isAck == true) {message.acknowledge();}if (isCommit == null) {} else if (isCommit == true) {session.commit();} else if (isCommit == false) {session.rollback();}}}@Afterpublic void close() throws JMSException {if (connection != null) {connection.close();}}}
package com.czy.demo.ActiveDemo.helloworld;import javax.jms.Connection;import javax.jms.ConnectionFactory;import javax.jms.DeliveryMode;import javax.jms.Destination;import javax.jms.JMSException;import javax.jms.MessageProducer;import javax.jms.Session;import javax.jms.TextMessage;import org.apache.activemq.ActiveMQConnectionFactory;import org.junit.After;import org.junit.Before;import org.junit.Test;/** * ActiveMQ 版本 5.14.2 * * @author chenzhiyuan * */public class Sender {Session session = null;MessageProducer producer = null;Connection connection = null;@Beforepublic void before() throws JMSException {// 1.创建ConnectionFactory工厂ConnectionFactory factory = new ActiveMQConnectionFactory("czy", "czy", "tcp://localhost:61616");// 2.创建Connectionconnection = factory.createConnection();connection.start();}@Testpublic void testQueue() throws JMSException {session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);// 4.创建目的地Destination des = session.createQueue("queue1");// 5.创建生产者producer = session.createProducer(des);// 6.发送消息send();// 测试结果在消费者里描述}@Testpublic void testTopic() throws JMSException {session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);// 4.创建目的地Destination des = session.createTopic("topic1");// 5.创建生产者producer = session.createProducer(des);// 6.发送消息send();// 测试结果在消费者里描述}@Testpublic void testTransaction() throws JMSException {// 3.创建session true开启事物,AUTO_ACKNOWLEDGE 自动提交// 这俩种方式创建Session,不影响下面发送消息的结果// session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);session = connection.createSession(true, Session.SESSION_TRANSACTED);// 4.创建目的地Destination des = session.createQueue("queue1");// 5.创建生产者producer = session.createProducer(des);// 6.生产消息// sendWithTransaction(true);// sendWithTransaction(false);// sendWithTransaction(null);/* * 依次取消上面注释,分别执行,得到测试结果 在开启事物的时候,只有显示提交时才会有消息进入队列 */}@Testpublic void testNoTransaction() throws JMSException {// 3.创建session false不开启事物,AUTO_ACKNOWLEDGE 自动提交session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);// 这样创建session会报错// session = connection.createSession(false,// Session.SESSION_TRANSACTED);// 4.创建目的地Destination des = session.createQueue("queue1");// 5.创建生产者producer = session.createProducer(des);// 6.生产消息sendWithTransaction(true);// sendWithTransaction(false);// sendWithTransaction(null);/* * 依次取消上面注释,分别执行,得到测试结果 在未开启事物的时候,显示提交或回滚会报错, 但是提交或者回滚前生产的那条记录,会入队成功。 */}@Testpublic void testAcknowledgeType() throws JMSException {// 3.创建session false不开启事物,CLIENT_ACKNOWLEDGE 自动提交// Session.AUTO_ACKNOWLEDGE 自动提交// Session.CLIENT_ACKNOWLEDGE 客户端手动确认// Session.DUPS_OK_ACKNOWLEDGE 自动批量提交// Session.SESSION_TRANSACTED 在事物的环境中session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);// 4.创建目的地Destination des = session.createQueue("queue1");// 5.创建生产者producer = session.createProducer(des);// SendWithAck(false);// SendWithAck(true);/* * 测试结果 无论哪种ACK类型,无论是否显示的进行却仍,都会入队成功, ACK的类型不影响生产者生产消息,或者说ACK机制就是针对客户端的 */}@Testpublic void testNonPersistent() throws JMSException {session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);// 4.创建目的地Destination des = session.createQueue("queue1");// 5.创建生产者producer = session.createProducer(des);// 非持久化// producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);producer.setDeliveryMode(DeliveryMode.PERSISTENT);// 发送消息send();/** * 测试结果 如果没有设置持久化,重启ActiveServer消息会丢失, 消费者接受不到消息, * 如果设置了持久化,重启之后消费者仍然能接受到消息 默认的持久化策略是kahadb,当然mysql,oracle等传统关系型数据库也可以 * 想不到什么情况下会有关系型数据库当成持久化策略,不演示 * */}@Testpublic void testMessageGroupId() throws JMSException {session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);// 4.创建目的地Destination des = session.createQueue("queue1");// 5.创建生产者producer = session.createProducer(des);// 6.发送消息for (int i = 0; i < 5; i++) {TextMessage message = session.createTextMessage();message.setText("我是消息内容i=" + i);message.setStringProperty("JMSXGroupID", "groupId11");producer.send(message);/* * 跟所有的消息都由唯一的consumer处理不同, JMS 消息属性JMSXGroupID 被用来区分message group。 * Message Groups特性保证所有具有相同JMSXGroupID 的消息 * 会被分发到相同的consumer(只要这个consumer保持active)。 另外一方面,Message * Groups特性也是一种负载均衡的机制。 * 在一个消息被分发到consumer之前,broker首先检查消息JMSXGroupID属性。 如果存在,那么broker * 会检查是否有某个consumer拥有这个message group。 * 如果没有,那么broker会选择一个consumer,并将它关联到这个message group。 * 此后,这个consumer会接收这个message group的所有消息,直到Consumer被关闭。 */ }}@Testpublic void testMessageSelector() throws JMSException {session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);// 4.创建目的地Destination des = session.createQueue("queue1");// 5.创建生产者producer = session.createProducer(des);// 6.发送消息for (int i = 0; i < 5; i++) {TextMessage message = session.createTextMessage();message.setIntProperty("number",i);message.setText("我是消息内容i=" + i);System.out.println("这是生产者:" + message.getText());producer.send(message);}}@Testpublic void testCompositeDestination() throws JMSException {session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);// 4.创建目的地Destination des = session.createQueue("queue1,queue2,queue3,queue4,queue5");// 5.创建生产者producer = session.createProducer(des);// 6.发送消息send();//CompositeDestination它允许用一个虚拟的destination 代表多个destinations。//例如你可以通过composite destinations在一个操作中同时向12个queue发送消息。//在composite destinations中,多个destination之间采用","分割//如果你希望使用不同类型的destination,那么需要加上前缀如queue:// 或topic://}public void send() throws JMSException {send(null, false);}public void sendWithTransaction(Boolean isCommit) throws JMSException {send(isCommit, false);}public void SendWithAck(Boolean isAck) throws JMSException {send(null, isAck);}public void send(Boolean isCommit, Boolean isAck) throws JMSException {// 发送消息for (int i = 0; i < 5; i++) {TextMessage message = session.createTextMessage();message.setText("我是消息内容i=" + i);producer.send(message);if (isAck == true) {message.acknowledge();}if (isCommit == null) {System.out.println("这是生产者:" + message.getText());} else if (isCommit == true) {session.commit();System.out.println("commit---这是生产者:" + message.getText());} else if (isCommit == false) {session.rollback();System.out.println("rollback---这是生产者:" + message.getText());}}}@Afterpublic void after() throws JMSException {if (connection != null) {connection.close();}}}
- activeMQ总结
- activemq 总结
- ActiveMQ总结
- ActiveMQ 总结
- ActiveMQ 使用总结
- ActiveMQ大总结
- ActiveMQ使用总结
- activemq知识总结
- ActiveMQ使用总结
- ActiveMQ使用总结
- ActiveMQ大总结
- activeMQ使用总结
- jms--activemq知识点总结
- ActiveMQ使用常见问题总结
- ActiveMq 学习总结
- ActiveMQ 总结(1)
- ActiveMQ的知识总结
- ActiveMQ使用总结
- 28个JavaScript常用代码集合
- HTTP 缓存原理介绍
- ffmpeg框架阅读笔记一:读取数据帧函数 int av_read_frame(AVFormatContext *s, AVPacket *pkt)
- Java知识盘点:Java的内存机制
- JavaWeb新的工作目录下新建jsp红叉提示
- ActiveMQ 总结
- centos7安装composer
- [python每日一练]--0004:统计文档内的单词个数
- SpringMVC 全局异常处理
- 浅析面对对象 六大原则(二)
- 制作一个支持SSH终端登录的镜像
- idea中引入jquery无效
- 安卓开发小技巧--TextView 设置的文字过长,显示三个点或者滚动形式显示
- TortoiseGit出现各种莫名的问题