JMS中点对点消息

    点对点消息传送模型允许JMS客户端通过队列(Queue)这个虚拟通道来同步和异步发送、接收消息。消息的生产者成为QueueSender,消费者为QueueReceiver。点对点模型是一个基于拉取(pull,即receive方式)或者基于轮询(polling,即异步接收)的消息传输模型,这种模型从队列中请求消息,而不是JMS Provider将消息自动的推送给客户端。发送到队列的任何一条消息,将会被一个而且仅仅一个消费者接收,即使有多个消费者侦听同一个队列。

    点对点消息传送模型,即支持异步“即发即弃”,又支持同步的“请求--应答”的消息发送方式。(稍后代码实例)

    点对点模型支持负载均衡,即多个消息消费者侦听同一个队列时,JMS Provider负责将这些消息以"某种策略"均衡的分发给它们.事实上点对点模型的负载均衡很容易实现,因为消息消费者只有处于"空闲时"才会向JMS Provider"索取"消息.对于Queue,还提供了使用Browser的方式查看队列消息而不消费它们.

    点对点消息模型,对于JMS Provider而言,就是一个队列,JMS Provider将会对消息按照其发送到队列的顺序排序.然后依次发送给消费者(权重优先),一旦消息被消费者接收(确认),消息将会从队列中移除.

    不过需要特殊强调一点:JMS Prodiver并不是严格的保证队列中消息移除的顺序,特别是在多个消费者Client时;当多个消费者同时侦听消息队列,JMS Prodiver将会把队列中的消息,依次转发给各个Client,此时如果消息被接收且确认,消息将会从队列中移除,此消息有可能并不是队列的第一个元素;当一个消息未能确认时,JMS Provider会将此消息不断的重发,直到重发次数达到阀值;一条消息不能正确接收,这种情况不会影响到队列中其他消息的正常消费;而且由于网络的问题,优先发送的消息,可能在消费者接收的时间上滞后.由此可见,依靠Queue来完全实现消息的队列化消费是错误的.(理想的情况是,一个消息接收确认之后,队列中此后的消息才会被发送给消费者).

    你可以简单的认为P2P消息模型的存储机制为:

+++++++++++++++
++MessageId   |    Created               |    Priority++
++100                 100000000000               3
++101                 100000002000               3
++102                 100000004000               2

    对于消息的发送顺序为"order by priority des,created asc",一旦发送成功,将会delete.

    点对点消息传送模型有两种:

    1) 即发即弃: 一种异步的消息发送和确认机制,Producer发送消息之后,它无需等待此消息被消费的"响应".

    2) 请求-应答: 一种同步机制,Producer发送消息之后,它阻塞,直到此消息被消费;当消息被消费时,将会向一个"响应队列"中发送一个"通知",那么对于Producer而言,就是接收到这个"通知后"才会返回.

###contextFactory
java.naming.factory.initial = org.apache.activemq.jndi.ActiveMQInitialContextFactory
###brokerUrl,any protocol
java.naming.provider.url = tcp://localhost:61616
##username
##java.naming.security.principal=
##password
##java.naming.security.credentials=
##connectionFactory,for building sessions
connectionFactoryNames = QueueCF,TopicCF
##topic.<topicName> = <physicalName-of-topic>
##your application should use <topicName>,such as:
## context.lookup("topic1");
##It can be more than once
topic.topic1 = jms.topic1
##queue.<topicName> = <physicalName-of-queue>
queue.queue1 = jms.queue1
///请求应答模式:生产者
package com.test.jms.simple;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.Session;
import javax.naming.Context;
import javax.naming.InitialContext;

public class SimpleProductor {

	private MessageProducer producer;
	private Session session;
	private Connection connection;
	private boolean isOpen = true;
	private Destination replyTo;
	
	public SimpleProductor() throws Exception{
		Context context = new InitialContext();
		ConnectionFactory connectionFactory = (QueueConnectionFactory)context.lookup("QueueCF");
		connection = connectionFactory.createConnection();
		session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
		Destination queue = (Queue)context.lookup("queue1");
		replyTo = (Queue)context.lookup("test-repyto");
		producer = session.createProducer(queue);
		producer.setDeliveryMode(DeliveryMode.PERSISTENT);
		connection.start();
		
	}
	
	
	public boolean send(String text) {
		if(!isOpen){
			throw new RuntimeException("session has been closed!");
		}
		try{
			Message message = session.createTextMessage(text);
			String cid = "ID:" + System.currentTimeMillis();
			message.setJMSCorrelationID(cid);
			producer.send(message);
			MessageConsumer consumer = session.createConsumer(replyTo,"JMSCorrelationID='" + cid + "'");
			//最多重发5次
			for(int i=0;i< 5;i++){
				Message replyMessage = consumer.receive(30000);
				if(replyMessage != null){
					System.out.println("Reply success:" + replyMessage.getJMSCorrelationID());
					break;
				}
			}
			consumer.close();
			return true;
		}catch(Exception e){
			return false;
		}
	}
	
	public synchronized void close(){
		try{
			if(isOpen){
				isOpen = false;
			}
			session.close();
			connection.close();
		}catch (Exception e) {
			//
		}
	}
	
}
//请求应答模式:消费者
package com.test.jms.simple;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.MessageConsumer;
import javax.jms.Queue;
import javax.jms.QueueConnectionFactory;
import javax.jms.Session;
import javax.naming.Context;
import javax.naming.InitialContext;

import com.test.jms.object.QueueMessageListener;

public class SimpleConsumer {

	private Connection connection;
	private Session session;
	private MessageConsumer consumer;
	
	private boolean isStarted;
	
	public SimpleConsumer() throws Exception{
		Context context = new InitialContext();
		ConnectionFactory connectionFactory = (QueueConnectionFactory)context.lookup("QueueCF");
		connection = connectionFactory.createConnection();
		session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
		Destination queue = (Queue)context.lookup("queue1");
		consumer = session.createConsumer(queue);
		consumer.setMessageListener(new QueueMessageListener(session));
		connection.start();
	}
	
	
	public synchronized boolean start(){
		if(isStarted){
			return true;
		}
		try{
			connection.start();
			isStarted = true;
			return true;
		}catch(Exception e){
			return false;
		}
	}
	
	public synchronized void close(){
		isStarted = false;
		try{
			session.close();
			connection.close();
		}catch(Exception e){
			//
		}
	}
}
///请求应答模式:消息侦听器
package com.test.jms.object;

import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;

public class QueueMessageListener implements MessageListener{

	private Session session;
	public QueueMessageListener(Session session){
		this.session = session;
	}
	public void onMessage(Message message) {
		if(message == null){
			return;
		}
		try{
			Destination replyTo = message.getJMSReplyTo();
			if(message instanceof TextMessage){
				String text = ((TextMessage)message).getText();
				System.out.println(text);
			}
			if(replyTo != null){
				message.clearBody();
				MessageProducer producer = session.createProducer(replyTo);
				producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
				producer.setTimeToLive(50000);
				producer.send(message);
				producer.close();
			}
			
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}

猜你喜欢

转载自shift-alt-ctrl.iteye.com/blog/1921713