activemq的几种基本通信方式总结.docx
- 文档编号:4413921
- 上传时间:2022-12-01
- 格式:DOCX
- 页数:18
- 大小:106.26KB
activemq的几种基本通信方式总结.docx
《activemq的几种基本通信方式总结.docx》由会员分享,可在线阅读,更多相关《activemq的几种基本通信方式总结.docx(18页珍藏版)》请在冰豆网上搜索。
activemq的几种基本通信方式总结
ActiveMQ的几种基本通信方式总结
简介
在前面一篇文章里讨论过几种应用系统集成的方式,发现实际上面向消息队列的集成方案算是一个总体比较合理的选择。
这里,我们先针对具体的一个消息队列Activemq的基本通信方式进行探讨。
activemq是JMS消息通信规范的一个实现。
总的来说,消息规范里面定义最常见的几种消息通信模式主要有发布-订阅、点对点这两种。
另外,通过结合这些模式的具体应用,我们在处理某些应用场景的时候也衍生出来了一种请求应答的模式。
下面,我们针对这几种方式一一讨论一下。
基础流程
在讨论具体方式的时候,我们先看看使用activemq需要启动服务的主要过程。
按照JMS的规范,我们首先需要获得一个JMSconnectionfactory.,通过这个connectionfactory来创建connection.在这个基础之上我们再创建session,destination,producer和consumer。
因此主要的几个步骤如下:
1.获得JMSconnectionfactory.通过我们提供特定环境的连接信息来构造factory。
2.利用factory构造JMSconnection
3.启动connection
4.通过connection创建JMSsession.
5.指定JMSdestination.
6.创建JMSproducer或者创建JMSmessage并提供destination.
7.创建JMSconsumer或注册JMSmessagelistener.
8.发送和接收JMSmessage.
9.关闭所有JMS资源,包括connection,session,producer,consumer等。
publish-subscribe
发布订阅模式有点类似于我们日常生活中订阅报纸。
每年到年尾的时候,邮局就会发一本报纸集合让我们来选择订阅哪一个。
在这个表里头列了所有出版发行的报纸,那么对于我们每一个订阅者来说,我们可以选择一份或者多份报纸。
比如北京日报、潇湘晨报等。
那么这些个我们订阅的报纸,就相当于发布订阅模式里的topic。
有很多个人订阅报纸,也有人可能和我订阅了相同的报纸。
那么,在这里,相当于我们在同一个topic里注册了。
对于一份报纸发行方来说,它和所有的订阅者就构成了一个1对多的关系。
这种关系如下图所示:
现在,假定我们用前面讨论的场景来写一个简单的示例。
我们首先需要定义的是publisher.
publisher
publisher是属于发布信息的一方,它通过定义一个或者多个topic,然后给这些topic发送消息。
publisher的构造函数如下:
Java代码
1.public Publisher() throws JMSException {
2. factory = new ActiveMQConnectionFactory(brokerURL);
3. connection = factory.createConnection();
4. try {
5. connection.start();
6. } catch (JMSException jmse) {
7. connection.close();
8. throw jmse;
9. }
10. session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
11. producer = session.createProducer(null);
12. }
我们按照前面说的流程定义了基本的connectionFactory,connection,session,producer。
这里代码就是主要实现初始化的效果。
接着,我们需要定义一系列的topic让所有的consumer来订阅,设置topic的代码如下:
Java代码
1.protected void setTopics(String[] stocks) throws JMSException {
2. destinations = new Destination[stocks.length];
3. for(int i = 0; i < stocks.length; i++) {
4. destinations[i] = session.createTopic("STOCKS." + stocks[i]);
5. }
6.}
这里destinations是一个内部定义的成员变量Destination[]。
这里我们总共定义了的topic数取决于给定的参数stocks。
在定义好topic之后我们要给这些指定的topic发消息,具体实现的代码如下:
Java代码
1.protected void sendMessage(String[] stocks) throws JMSException {
2. for(int i = 0; i < stocks.length; i++) {
3. Message message = createStockMessage(stocks[i], session);
4. System.out.println("Sending:
" + ((ActiveMQMapMessage)message).getContentMap() + " on destination:
" + destinations[i]);
5. producer.send(destinations[i], message);
6. }
7.}
8.
9.protected Message createStockMessage(String stock, Session session) throws JMSException {
10. MapMessage message = session.createMapMessage();
11. message.setString("stock", stock);
12. message.setDouble("price", 1.00);
13. message.setDouble("offer", 0.01);
14. message.setBoolean("up", true);
15.
16. return message;
17.}
前面的代码很简单,在sendMessage方法里我们遍历每个topic,然后给每个topic发送定义的Message消息。
在定义好前面发送消息的基础之后,我们调用他们的代码就很简单了:
Java代码
1.public static void main(String[] args) throws JMSException {
2. if(args.length < 1)
3. throw new IllegalArgumentException();
4.
5. // Create publisher
6. Publisher publisher = new Publisher();
7.
8. // Set topics
9. publisher.setTopics(args);
10.
11. for(int i = 0; i < 10; i++) {
12. publisher.sendMessage(args);
13. System.out.println("Publisher '" + i + " price messages");
14. try {
15. Thread.sleep(1000);
16. } catch(InterruptedException e) {
17. e.printStackTrace();
18. }
19. }
20. // Close all resources
21. publisher.close();
22.}
调用他们的代码就是我们遍历所有topic,然后通过sendMessage发送消息。
在发送一个消息之后先sleep1秒钟。
要注意的一个地方就是我们使用完资源之后必须要使用close方法将这些资源关闭释放。
close方法关闭资源的具体实现如下:
Java代码
1.public void close() throws JMSException {
2. if (connection !
= null) {
3. connection.close();
4. }
5.}
consumer
Consumer的代码也很类似,具体的步骤无非就是1.初始化资源。
2.接收消息。
3.必要的时候关闭资源。
初始化资源可以放到构造函数里面:
Java代码
1.public Consumer() throws JMSException {
2. factory = new ActiveMQConnectionFactory(brokerURL);
3. connection = factory.createConnection();
4. connection.start();
5. session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
6. }
接收和处理消息的方法有两种,分为同步和异步的,一般同步的方式我们是通过MessageConsumer.receive()方法来处理接收到的消息。
而异步的方法则是通过注册一个MessageListener的方法,使用MessageConsumer.setMessageListener()。
这里我们采用异步的方式实现:
Java代码
1.public static void main(String[] args) throws JMSException {
2. Consumer consumer = new Consumer();
3. for (String stock :
args) {
4. Destination destination = consumer.getSession().createTopic("STOCKS." + stock);
5. MessageConsumer messageConsumer = consumer.getSession().createConsumer(destination);
6. messageConsumer.setMessageListener(new Listener());
7. }
8.}
9.
10.public Session getSession() {
11. return session;
12.}
在前面的代码里我们先找到同样的topic,然后遍历所有的topic去获得消息。
对于消息的处理我们专门通过Listener对象来负责。
Listener对象的职责很简单,主要就是处理接收到的消息:
Java代码
1.public class Listener implements MessageListener {
2.
3. public void onMessage(Message message) {
4. try {
5. MapMessage map = (MapMessage)message;
6. String stock = map.getString("stock");
7. double price = map.getDouble("price");
8. double offer = map.getDouble("offer");
9. boolean up = map.getBoolean("up");
10. DecimalFormat df = new DecimalFormat( "#,###,###,##0.00" );
11. System.out.println(stock + "\t" + df.format(price) + "\t" + df.format(offer) + "\t" + (up?
"up":
"down"));
12. } catch (Exception e) {
13. e.printStackTrace();
14. }
15. }
16.
17.}
它实现了MessageListener接口,里面的onMessage方法就是在接收到消息之后会被调用的方法。
现在,通过实现前面的publisher和consumer我们已经实现了pub-sub模式的一个实例。
仔细回想它的步骤的话,主要就是要两者设定一个共同的topic,有了这个topic之后他们可以实现一方发消息另外一方接收。
另外,为了连接到具体的messageserver,这里是使用了连接tcp:
//localhost:
16161作为定义ActiveMQConnectionFactory的路径。
在publisher端通过session创建producer,根据指定的参数创建destination,然后将消息和destination作为producer.send()方法的参数发消息。
在consumer端也要创建类似的connection,session。
通过session得到destination,再通过session.createConsumer(destination)来得到一个MessageConsumer对象。
有了这个MessageConsumer我们就可以自行选择是直接同步的receive消息还是注册listener了。
p2p
p2p的过程则理解起来更加简单。
它好比是两个人打电话,这两个人是独享这一条通信链路的。
一方发送消息,另外一方接收,就这么简单。
在实际应用中因为有多个用户对使用p2p的链路,它的通信场景如下图所示:
我们再来看看一个p2p的示例:
在p2p的场景里,相互通信的双方是通过一个类似于队列的方式来进行交流。
和前面pub-sub的区别在于一个topic有一个发送者和多个接收者,而在p2p里一个queue只有一个发送者和一个接收者。
发送者
和前面的示例非常相似,我们构造函数里需要初始化的内容基本上差不多:
Java代码
1.public Publisher() throws JMSException {
2. factory = new ActiveMQConnectionFactory(brokerURL);
3. connection = factory.createConnection();
4. connection.start();
5. session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
6. producer = session.createProducer(null);
7.}
发送消息的方法如下:
Java代码
1.public void sendMessage() throws JMSException {
2. for(int i = 0; i < jobs.length; i++)
3. {
4. String job = jobs[i];
5. Destination destination = session.createQueue("JOBS." + job);
6. Message message = session.createObjectMessage(i);
7. System.out.println("Sending:
id:
" + ((ObjectMessage)message).getObject() + " on queue:
" + destination);
8. producer.send(destination, message);
9. }
10.}
这里我们定义了一个jobs的数组,通过遍历这个数组来创建不同的jobqueue。
这样就相当于建立了多个点对点通信的链路。
消息发送者的启动代码如下:
Java代码
1.public static void main(String[] args) throws JMSException {
2. Publisher publisher = new Publisher();
3. for(int i = 0; i < 10; i++) {
4. publisher.sendMessage();
5. System.out.println("Published " + i + " job messages");
6. try {
7. Thread.sleep(1000);
8. } catch (InterruptedException x) {
9. e.printStackTrace();
10. }
11. }
12. publisher.close();
13.}
我们在这里发送10条消息,当然,在每个sendMessage的方法里实际上是针对每个queue发送了10条。
接收者
接收者的代码很简单,一个构造函数初始化所有的资源:
Java代码
1.public Consumer() throws JMSException {
2. factory = new ActiveMQConnectionFactory(brokerURL);
3. connection = factory.createConnection();
4. connection.start();
5. session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
6. }
还有一个就是注册消息处理的对象:
Java代码
1.public static void main(String[] args) throws JMSException {
2. Consumer consumer = new Consumer();
3. for (String job :
consumer.jobs) {
4. Destination destination = consumer.getSession().createQueue("JOBS." + job);
5. MessageConsumer messageConsumer = consumer.getSession().createConsumer(destination);
6. messageConsumer.setMessageListener(new Listener(job));
7. }
8. }
9.
10. public Session getSession() {
11. return session;
12. }
具体注册的对象处理方法和前面还是类似,实现MessageListener接口就可以了。
Java代码
1.import javax.jms.Message;
2.import javax.jms.MessageListener;
3.import javax.jms.ObjectMessage;
4.
5.public class Listener implements MessageListener {
6.
7. private String job;
8.
9. public Listener(String job) {
10. this.job = job;
11. }
12.
13. public void onMessage(Message message) {
14. try {
15. //do something here
16. System.out.println(job + " id:
" + ((ObjectMessage)me
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- activemq 基本 通信 方式 总结