rbbitmq 怎么区分 订阅/activemq发布订阅模式 和 生产消费

6183人阅读
apache kafka(73)
JMS一个在 Java标准化组织(JCP)内开发的标准(代号JSR 914)。日,Java消息服务发布JMS 1.0.2b,日Java消息服务发布 1.1.
Java消息服务(Java Message Service,JMS)应用程序接口是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。
点对点与发布订阅最初是由JMS定义的。这两种模式主要区别或解决的问题就是发送到队列的消息能否重复消费(多订阅)
1.JMS中定义
JMS规范目前支持两种消息模型:点对点(point to point, queue)和发布/订阅(publish/subscribe,topic)。
消息生产者生产消息发送到queue中,然后消息消费者从queue中取出并且消费消息。这里要注意:
消息被消费以后,queue中不再有存储,所以消息消费者不可能消费到已经被消费的消息。
Queue支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费。
消息生产者(发布)将消息发布到topic中,同时有多个消息消费者(订阅)消费该消息。和点对点方式不同,发布到topic的消息会被所有订阅者消费。
2.二者分析与区别
2.1 点对点模式
生产者发送一条消息到queue,只有一个消费者能收到。
2.2 发布订阅模式
发布者发送到topic的消息,只有订阅了topic的订阅者才会收到消息。
queue实现了负载均衡,一个消息只能被一个消费者接受,当没有消费者可用时,这个消息会被保存直到有 一个可用的消费者,一个queue可以有很多消费者,他们之间实现了负载均衡,
所以Queue实现了一个可靠的负载均衡。
topic实现了发布和订阅,当你发布一个消息,所有订阅这个topic的服务都能得到这个消息,所以从1到N个订阅者都能得到一个消息的拷贝,
只有在消息代理收到消息时有一个有效订阅时的订阅者才能得到这个消息的拷贝。
发布订阅模式下,能否实现订阅者负载均衡消费呢?当发布者消息量很大时,显然单个订阅者的处理能力是不足的。实际上现实场景中是多个订阅者节点组成一个订阅组负载均衡消费topic消息即分组订阅,
这样订阅者很容易实现消费能力线性扩展。
3 流行消息队列模型比较
传统企业型消息队列ActiveMQ遵循了JMS规范,实现了点对点和发布订阅模型,但其他流行的消息队列RabbitMQ、Kafka并没有遵循老态龙钟的JMS规范,是通过什么方式实现消费负载均衡、多订阅呢?
3.1 RabbitMQ
RabbitMQ实现了AQMP协议,AQMP协议定义了消息路由规则和方式。生产端通过路由规则发送消息到不同queue,消费端根据queue名称消费消息。此外RabbitMQ是向消费端推送消息,订阅关系和消费状态保存在服务端。
生产端发送一条消息通过路由投递到Queue,只有一个消费者能消费到。
当RabbitMQ需要支持多订阅时,发布者发送的消息通过路由同时写到多个Queue,不同订阅组消费此消息。
RabbitMQ既支持内存队列也支持持久化队列,消费端为推模型,消费状态和订阅关系由服务端负责维护,消息消费完后立即删除,不保留历史消息。所以支持多订阅时,消息会多个拷贝。
Kafka只支持消息持久化,消费端为拉模型,消费状态和订阅关系由客户端端负责维护,消息消费完后不会立即删除,会保留历史消息。因此支持多订阅时,消息只会存储一份就可以了。
&&相关文章推荐
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:608794次
积分:7597
积分:7597
排名:第2493名
原创:188篇
转载:26篇
评论:174条
(7)(1)(1)(7)(1)(13)(8)(5)(2)(1)(1)(2)(4)(10)(11)(3)(11)(3)(3)(2)(10)(6)(18)(25)(6)(1)(2)(1)(1)(18)(13)(1)(4)(1)(2)(2)(1)(1)(1)(3)(2)WebSphere MQ Version 7 发布订阅相关配置 - qtlkw - ITeye技术网站
Message-oriented middleware (MOM) decouples applications by allowing them to communicate using one of two messaging models: point-to-point messaging and publish/subscribe messaging. The models differ in fundamental ways, but neither requires applications to know the other’s implementation details.
Point-to-point messaging achieves only partial decoupling of applications, because you still need to know where to put messages. Publish/subscribe provides a higher degree of independence and reduces design complexity in many cases, but it requires more coding and configuration. Traditionally, MOM shops have opted for point-to-point messaging to avoid the more complex requirements of publish/subscribe.
Enter IBM WebSphere MQ (WMQ), Version 7. This latest release of WMQ aims to make coding and configuring publish/subscribe easier and more intuitive. A previous DevX article focused on the point-to-point messaging capabilities of WMQ. This article explains WMQ's publish/subscribe messaging.
Publish/Subscribe Messaging Overview
Publish/subscribe is the messaging-oriented equivalent of the object-oriented observer design pattern. In publish/subscribe messaging, a sender application creates a message containing the information it wants to send and assigns it a topic that denotes the subject of the information. This message is called a publication. WMQ receives the publication, recognizes the topic, and then distributes the publication to interested applications.
Specifically, WMQ publish/subscribe components include:
& Publisher (information producer): This component generates messages (publications) under a certain subject (topic) and sends the publications to a WMQ queue manager. A publisher knows nothing about the recipient(s) of the information.
& Subscriber (information consumer/receiver): This component registers interest in a certain topic(s) with a WMQ queue manager. It also specifies its sub that is, the queue where it wants to receive the messages related to this topic. The subscriber knows nothing about the information publishers(s).
& A publications router: This component passes messages from publishers to topic subscribers. Earlier WMQ versions required a broker component on top of a queue manager to enable publish/subscribe. The broker maintained topics and subscriptions, and it routed publications. In WMQ Version 7, IBM changed this approach significantly. The queue manager is now responsible for topics, subscriptions, and routing publications. Also, MQ Explorer for Version 7 allows you to create topics and subscriptions graphically.
Figure 1 shows a basic MQ publish/subscribe setup.
A publish/subscribe system can have many publishers and many subscribers, and often, two or more queue managers communicating with one another. Also, an application can be both a publisher and a subscriber.
A Publish/Subscribe Scenario
Suppose a company sends notifications to its clients via email and Short Message Service (SMS) based on information received from various information providers (say, news and weather services). If the company adds another provider (say, for entertainment), it will have to configure the new provider to write messages to both SMS and email queues. Figure 2 shows the point-to-point implementation for this use case, and Figure 3 shows the publish/subscribe implementation.
Set Up Your Own Publish/Subscribe Use Case
In this section, you will create a publish/subscribe setup resembling part of the use case in Figure 3. You will create a publisher for the news topic and two subscriptions for the email and SMS applications using the following procedure:
&& 1. Create a queue manager.
&& 2. Create a news topic.
&& 3. Create subscription queues.
&& 4. Create subscriptions.
&& 5. Create Java Messaging Services (JMS)-administered objects.
&& 6. Write publisher and subscriber classes.
&& 7. Run the classes.
This tutorial uses MQ Version 7 on Windows XP. (Download a trial version from the IBM web site.) Installation on Windows is straightforward. Just keep all the default values as you go through the installation wizard, but be sure to perform the installation as a user from the administrators group.
Don't worry if you haven't used WMQ before. You will use the Eclipse-based WebSphere MQ Explorer, an easy GUI for administering WMQ, to perform basic definitions.
Start WebSphere MQ Explorer as follows: Start –& All Programs –& IBM WebSphere MQ –& WebSphere MQ Explorer. If this is the first time you are starting MQ Explorer, a welcome screen will appear. Just close the welcome screen.
Create a Queue Manager
&& 1. In MQ Explorer's Navigator view, right-click Queue Managers and then select New –& Queue Manager. This starts the "Create Queue Manager" wizard.
&& 2. On Step 1, enter TestQM as the queue manager name and enter the name of the default Dead Letter Queue which is SYSTEM.DEAD.LETTER.QUEUE, then click Next (see Figure 4).
&& 3. Click Next on the wizard screens for Steps 2 and 3. At Step 4, make sure "Create listener configured for TCP/IP" is checked and the entered port number is free (see Figure 5), and then click Finish.
Create a News Topic
&& 1. Under TestQM, right-click Topics and then select New –& Topic to start the "New Topic" wizard.
&& 2. Type News.Topic as the topic name (see Figure 6). This represents the WMQ administrative object used to manage the topic. Click Next.
&& 3. On the topic properties page, type News in the "Topic string" field (see Figure 7). This string is used when creating JMS administered objects to refer to the News topic. Click Finish.
Create Subscription Queues
Next, you will set up news publications to be delivered to Subscription queues. Create two queues for the email and SMS applications:
&& 1. Under TestQM, right-click Queues then select New –& Local Queue to start the "New Local Queue" wizard.
&& 2. In the name field, type Email.Queue and click Finish.
&& 3. Repeat the above steps to create another queue called SMS.Queue.
Create Subscriptions
In order to receive a topic's publications, subscribers have to register interest in the topic. They use subscriptions to accomplish this. You can can create subscriptions programmatically or through MQ Explorer. Through the following steps, you will create two subscriptions using MQ Explorer:
&& 1. Under TestQM, right-click Subscriptions and then select New –& Subscription to start the "New Subscription" wizard.
&& 2. In the name field, type EmailSubscription and click Next (see Figure8). In the "Change properties" page, press the Select button next to the "Topic name" and then select News.Topic from the displayed topics list. Press OK. On the same page, type Email.Queue in the destination name field (see Figure 9). Click Finish.
& 3. Repeat the above steps to create another subscription called SMSSubscription with the topic set to News.Topic& and the destination name set to SMS.Queue.
A Quick Test for Your Publish/Subscribe Setup
Perform the following to verify you have correctly completed the setup for the News topic:
&& 1. Under TestQM, click Topics.
&& 2. In the right pane, right click News.Topic and select "Test Publication" to open the test window.
&& 3. In the message data field, type "publish/subscribe test" (or any other text), click the "Publish message" button, and then click the Close button. This should distribute the message to the subscriber queues Email.Queue and SMS.Queue.
&& 4. Under TestQM, click Queues.
&& 5. In the right pane, right click Email.Queue and select "Browse Messages." When the browse messages window opens, search the "Message Data" column for the text you entered. You should also see the same message in SMS.Queue.
&& 6. Right click Email.Queue and select "Clear Messages." Click the Clear button in the "Clear queue" window. Do the same for SMS.Queue.
Create JMS-Administered Objects
JMS applications require you to wrap vendor-specific objects in JMS-administered objects. To store JMS-administered objects, create a file-based Java Naming and Directory Interface (JNDI) namespace. Start by adding a new initial context:
&& 1. Right-click JMS-Administered Objects and then select Add Initial Context.
&& 2. On Screen 1:
&&&&&&&&&&&&&&&&& Select "File System" for "Where is the JNDI located."
&&&&&&&&&&&&&&&&& For the Bindings directory, browse to C:\JNDI-Directory& (This directory has to exist).
&&&&&&&&&&&&&&&&& Keep note of the factory class and provider URL; you will use them in the Java code (see Figure 10).
&&&&&&&&&&&&&&&&& Click Finish.
Next, create a JMS Connection factory and destinations under the Initial Context.
Create a Connection Factory
&& 1. Right-click Connection Factories and then select New –& Connection Factory. On the first screen, type TestQMConnectionFactory in the name field and click Next (see Figure 11). You will use TestQMConnectionFactory in the JNDI lookup.
&& 2. Click Next on Step 2, Step 3, and Step 4.
&& 3. On the last page, select the connection tab (on the left) and then click the Select button to select TestQM as "Base queue manager" (See Figure 12). Click Finish.
Create Destinations
JMS destinations wrap WMQ topics and queues. Create a destination corresponding to the News topic:
&& 1. Right-click destinations and select New –& Destination to start the "New Destination" wizard.
&& 2. In the first step, enter NewsTopic in the Name field and change the Type field to Topic (See Figure 13). Click Next.
&& 3. Click Next on the second screen.
&& 4. On the last page (Change properties), type News in the Topic field and then click Finish (See Figure 14). This is the topic string you defined when you created the News topic.
Create two destinations corresponding to the subscriber queues:
&& 1. Right-click destinations and then select New –& Destination to start the new "Destination wizard."
&& 2. In the first step, type EmailQueue in the Name field and then click Next.
&& 3. Click Next on the second screen.
&& 4. On the last page, click the Select button next to the "Queue Manager" field and select TestQM from the list.
&& 5. Click the Select button next to the Queue field and select Email (See Figure 15). Queue from the list. Click Finish.
&& 6. Repeat the above steps to create another Destination called SMSQueue for SMS.Queue. Your destinations should look like the ones in Figure 16.
Coding JMS Publishers and Subscribers
After you have defined your topics and subscriptions through the MQ Explorer, writing publisher and subscriber applications is easy. To publish a message, you must write a message to a topic (just as you would with a queue). Subscribers simply read messages from queues.
The downloadable source code for this article uses generic JMS interfaces, which treat queues and topics uniformly as destinations. It provides compiled classes that include a News publisher and two subscribers (corresponding to the Email and SMS applications).
The following are brief explanations of the classes.
JNDIUtil Class
This class includes methods to retrieve objects by name through JNDI lookup (see Listing 1). Listing 1. JNDIUtil Class
This class includes methods to retrieve objects by name through JNDI lookup.
package devx.articles.
//JMS classes
import javax.jms.JMSE
import javax.jms.ConnectionF
import javax.jms.D
//JNDI classes
import javax.naming.InitialC
import javax.naming.C
import javax.naming.NamingE
//Standard Java classes
import java.util.H
* A wrapper class for JNDI calls
public class JNDIUtil
public JNDIUtil(String icf, String url) throws JMSException, NamingException
Hashtable environment = new Hashtable();
environment.put(Context.INITIAL_CONTEXT_FACTORY, icf );
environment.put(Context.PROVIDER_URL, url);
context= new InitialContext( environment );
* @param ObjName Object Name to be retrieved
* @return Retrieved Object
* @throws NamingException
private Object getObjectByName(String ObjName) throws NamingException
return context.lookup( ObjName );
* @param factoryName Factory Name
* @return ConnectionFactory object
* @throws NamingException
public ConnectionFactory getConnectionFactory(String factoryName) throws NamingException
return (ConnectionFactory) getObjectByName(factoryName);
* @param destinationName Destination Name
* @return ConnectionFactory object
* @throws NamingException
public Destination getDestination(String destinationName) throws NamingException
return (Destination) getObjectByName(destinationName);
} You will use methods in this class to retrieve references to the JMS objects you have already defined.
NewsPublisher Class
This class publishes messages to the News topic (see Listing 2).package devx.articles.
//JMS classes
import javax.jms.JMSE
import javax.jms.ConnectionF
import javax.jms.C
import javax.jms.S
import javax.jms.D
import javax.jms.MessageP
import javax.jms.TextM
//JNDI classes
import javax.naming.NamingE
* A class to demonstrate how to a publish to a topic.
public class NewsPublisher
public static String icf = "com.sun.jndi.fscontext.RefFSContextFactory";
public static String url = "file:/C:/JNDI-Directory";
public static void main(String[] vars) throws JMSException, NamingException
ConnectionFactory factory =
Connection connection =
Session session =
Destination destination= // a destination can be a topic or a queue
MessageProducer producer=
JNDIUtil jndiUtil= new JNDIUtil(icf,url);
factory= jndiUtil.getConnectionFactory("TestQMConnectionFactory");
connection = factory.createConnection();
connection.start();
// Indicate a non-transactional session
boolean transacted =
session = connection.createSession( transacted, Session.AUTO_ACKNOWLEDGE);
destination = jndiUtil.getDestination("NewsTopic");
producer = session.createProducer(destination);
TextMessage message = session.createTextMessage("No News is Good News!");
producer.send(message);
System.out.println("NewsPublisher: Message Publication Completed");
// Always release resources
if ( producer!= null )
producer.close();
if ( session!= null )
session.close();
if ( connection!= null )
connection.close();
The starting point is a connection factory lookup. You use the factory to create a connection:
factory= jndiUtil.getConnectionFactory("TestQMConnectionFactory");
connection = factory.createConnection();
You use the connection object to create a session:
session = connection.createSession( transacted, Session.AUTO_ACKNOWLEDGE);
To publish messages, retrieve a News destination object, create a MessageProducer, and then send messages:
destination = jndiUtil.getDestination("NewsTopic");
producer = session.createProducer(destination);
TextMessage message = session.createTextMessage("No News is Good News!");
producer.send(message);
EmailSubscriber and SMSSubscriber
These two classes represent the email application and the SMS application (see Listing 3 and Listing 4). Because you already defined subscriptions in MQ Explorer, the two applications simply read messages from the subscriber queues.
Listing 3. EmailSubscriber
This class represents the email application.
package devx.articles.
//JMS classes
import javax.jms.JMSE
import javax.jms.ConnectionF
import javax.jms.C
import javax.jms.S
import javax.jms.D
import javax.jms.MessageC
import javax.jms.TextM
//JNDI classes
import javax.naming.NamingE
* A class to demonstrate how to retrieve publications from subscription queues.
public class EmailSubscriber
public static String icf = "com.sun.jndi.fscontext.RefFSContextFactory";
public static String url = "file:/C:/JNDI-Directory";
public static void main(String[] vars) throws JMSException, NamingException
ConnectionFactory factory =
Connection connection =
Session session =
Destination destination= // a destination can be a topic or a queue
MessageConsumer consumer=
JNDIUtil jndiUtil= new JNDIUtil(icf,url);
factory= jndiUtil.getConnectionFactory("TestQMConnectionFactory");
connection = factory.createConnection();
connection.start();
// Indicate a non-transactional session
boolean transacted =
session = connection.createSession( transacted, Session.AUTO_ACKNOWLEDGE);
destination = jndiUtil.getDestination("EmailQueue");
consumer = session.createConsumer(destination);
TextMessage iMsg = (TextMessage) consumer.receive(1000);
if ( iMsg != null )
System.out.println(
iMsg.getText()
System.out.println(
"No messages in queue "
System.out.println("EmailSubscriber: Message Reading Completed");
// Always release resources
if ( consumer!= null )
consumer.close();
if ( session!= null )
session.close();
if ( connection!= null )
connection.close();
}Listing 4. SMSSubscriber
This class represents the SMS application.
package devx.articles.
//JMS classes
import javax.jms.JMSE
import javax.jms.ConnectionF
import javax.jms.C
import javax.jms.S
import javax.jms.D
import javax.jms.MessageC
import javax.jms.TextM
//JNDI classes
import javax.naming.NamingE
* A class to demonstrate how to retrieve publications from subscription queues.
public class SMSSubscriber
public static String icf = "com.sun.jndi.fscontext.RefFSContextFactory";
public static String url = "file:/C:/JNDI-Directory";
public static void main(String[] vars) throws JMSException, NamingException
ConnectionFactory factory =
Connection connection =
Session session =
Destination destination= // a destination can be a topic or a queue
MessageConsumer consumer=
JNDIUtil jndiUtil= new JNDIUtil(icf,url);
factory= jndiUtil.getConnectionFactory("TestQMConnectionFactory");
connection = factory.createConnection();
connection.start();
// Indicate a non-transactional session
boolean transacted =
session = connection.createSession( transacted, Session.AUTO_ACKNOWLEDGE);
destination = jndiUtil.getDestination("SMSQueue");
consumer = session.createConsumer(destination);
TextMessage iMsg = (TextMessage) consumer.receive(1000);
if ( iMsg != null )
System.out.println(
iMsg.getText()
System.out.println(
"No messages in queue "
System.out.println("SMSSubscriber: Message Reading Completed");
// Always release resources
if ( consumer!= null )
consumer.close();
if ( session!= null )
session.close();
if ( connection!= null )
connection.close();
The code is similar to the NewsPublisher class, except that it uses a MessageConsumer to retrieve messages from queues:
consumer = session.createConsumer(destination);
TextMessage iMsg = (TextMessage) consumer.receive(1000);
Compiling and Running the Sample Classes
The JAR files required to compile and run the sample classes are automatically added to the CLASSPATH environment variable when you install WMQ. The required JARs are located in C:\Program Files\IBM\WebSphere MQ\Java\lib, including the JARs you need for JMS and JNDI. You just need to add the sample classes from the code download to your CLASSPATH environment variable.
To publish messages, run the NewsPublisher:
java devx.articles.pubsub.NewsPublisher
Run both subscribers after your run the NewsPublisher to retrieve messages. Each class should retrieve its own copy of the messages published by NewsPublisher:
java devx.articles.pubsub.EmailSubscriber
java devx.articles.pubsub.SMSSubscriber
You're done. Your sample classes should compile and run successfully.
So the next time you're designing messaging-based applications, don't be so quick to dismiss publish/subscribe. Remember this article and how quickly you were able to get started with publish/subscribe messaging.
WebSphere Version 6 和 Version 7的不同参考:
浏览: 161477 次
来自: 杭州
点赞,有空深入讲解下原理
Eclipse中高亮设置内容还有很多细节选项可以设置的,可以看 ...
这个时候,怎么启动发布的项目呢?????
非常感谢,楼主的英语水平不一般那
slave没玩过}

我要回帖

更多关于 activemq 订阅模式 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信