ActiveMQ学习

1. 概述

ActiveMQ是一种开源的基于JMS(Java Message Service)规范的一种消息中间件的实现,ActiveMQ的设计目标是提供标准的,面向消息的,能够跨越多语言和多系统的应用集成消息通信中间件(消息中间件)。
JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。Java消息服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供支持。我们可以简单的理解:两个应用程序之间需要进行通信,我们使用一个JMS服务,进行中间的转发,通过JMS 的使用,我们可以解除两个程序之间的耦合。

2. 消息中间件的作用

主要作用是消除高并发访问高峰,加快数据传输速度,消息队列的消费者进程从消息队列中获取数据,异步写入数据库,从而也减小了数据库压力。主要解决应用耦合,异步消息,流量削锋等问题。它实现高性能,高可用,可伸缩和最终一致性架构,是大型分布式系统不可缺少的中间件。

3. JMS的优势

Asynchronous(异步):JMS原本就是一个异步的消息服务,客户端获取消息的时候,不需要主动发送请求,消息会自动发送给可用的客户端。
Reliable(可靠性):JMS保证消息只会递送一次。

4. JMS的消息模型

  • Point-to-Point Messaging Domain (点对点)
  • Publish/Subscribe Messaging Domain (发布/订阅模式)

在JMS API出现之前,大部分产品使用“点对点”和“发布/订阅”中的任一方式来进行消息通讯。JMS定义了这两种消息发送模型的规范,它们相互独立。任何JMS的提供者可以实现其中的一种或两种模型,这是它们自己的选择。JMS规范提供了通用接口保证我们基于JMS API编写的程序适用于任何一种模型。

4.1 Point-To-Point模型

在点对点通信模式中,应用程序由消息队列,发送方,接收方组成。每个消息都被发送到一个特定的队列,接收者从队列中获取消息。队列保留着消息,直到他们被消费或超时。模型如下图:
在这里插入图片描述
特点:

  • 每个消息只要一个消费者。
  • 发送者和接收者在时间上是没有时间的约束,也就是说发送者在发送完消息之后,不管接收者有没有接受消息,都不会影响发送方发送消息到消息队列中。
  • 发送方不管是否在发送消息,接收方都可以从消息队列中去到消息。
  • 接收方在接收完消息之后,需要向消息队列应答成功。

4.2 Publish/Subscribe 模型

在发布/订阅消息模型中,发布者发布一个消息,该消息通过topic传递给所有的客户端。该模式下,发布者与订阅者都是匿名的,即发布者与订阅者都不知道对方是谁。并且可以动态的发布与订阅Topic。Topic主要用于传递消息。模型图如下:
在这里插入图片描述
特点:

  • 一个消息可以传递个多个订阅者(即:一个消息可以有多个接受方)
  • 发布者与订阅者具有时间约束,针对某个主题(Topic)的订阅者,它必须创建一个订阅者之后,才能消费发布者的消息,而且为了消费消息,订阅者必须保持运行的状态。
  • 为了缓和这样严格的时间相关性,JMS允许订阅者创建一个可持久化的订阅。这样,即使订阅者没有被激活(运行),它也能接收到发布者的消息。

5. JMS的编程模型

  • 管理对象(Administered objects)-连接工厂(Connection Factories)和目的地(Destination)
  • 连接对象(Connections)
  • 会话(Sessions)
  • 消息生产者(Message Producers)
  • 消息消费者(Message Consumers)
  • 消息监听者(Message Listeners)
    在这里插入图片描述
  • Connection Factories
    创建Connection对象的工厂,针对两种不同的jms消息模型,分别有QueueConnectionFactory和TopicConnectionFactory两种。可以通过JNDI来查找ConnectionFactory对象。客户端使用一个连接工厂对象连接到JMS服务提供者,它创建了JMS服务提供者和客户端之间的连接。JMS客户端(如发送者或接受者)会在JNDI名字空间中搜索并获取该连接。使用该连接,客户端能够与目的地通讯,往队列或话题发送/接收消息。
  • Destination
    目的地指明消息被发送的目的地以及客户端接收消息的来源。JMS使用两种目的地,队列和话题。
    对于消息生产者来说,它的Destination是某个队列(Queue)或某个主题(Topic);对于消息消费者来说,它的Destination也是某个队列或主题(即消息来源)。可以通过JNDI来查找Destination。
  • Connection
    表示在客户端和JMS系统之间建立的链接(对TCP/IP socket的包装)。Connection可以产生一个或多个Session。跟ConnectionFactory一样,Connection也有两种类型:QueueConnection和TopicConnection。连接对象封装了与JMS提供者之间的虚拟连接,如果我们有一个ConnectionFactory对象,可以使用它来创建一个连接。
  • Session
    Session 是我们对消息进行操作的接口,可以通过session创建生产者、消费者、消息等。Session 提供了事务的功能,如果需要使用session发送/接收多个消息时,可以将这些发送/接收动作放到一个事务中。
  • Producer
    消息生产者由Session创建,用于往目的地发送消息。生产者实现MessageProducer接口,我们可以为目的地、队列或话题创建生产者;
  • Consumer
    消息消费者由Session创建,用于接收被发送到Destination的消息。
  • MessageListener
    消息监听器。如果注册了消息监听器,一旦消息到达,将自动调用监听器的onMessage方法。EJB中的MDB(Message-Driven Bean)就是一种MessageListener。

6.ActiveMQ安装部署

(1)下载地址:http://activemq.apache.org/components/classic/download/
选择Linux版本:
在这里插入图片描述
(2)在Linux后台输入命令上传下载的压缩包:rz -bey
(3)解压缩:tar zxvf apache-activemq-5.15.11-bin.tar.gz
(4)进入apache-activemq-5.15.11/bin目录下,输入启动命令:./activemq start
启动成功为如下界面:
在这里插入图片描述
查看ActiveMQ的启动状态:./activemq status
停止ActiveMQ运行:./activemq stop
(5)在浏览器上输入http://127.0.0.1:8161,选择Manage ActiveMQ broker便可进入管理界面
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.代码示例:

ActiveMQ主题发布者代码:

public class ActiveMqPublisher {
	//日志对象
	private static Logger log = Logger.getLogger(ActiveMqProducer.class);
	//activeMQ的ip
    private static final String ACTIVEMQ_IP = "127.0.0.1";
    //activeMQ的端口,默认为61616
    private static final String ACTIVEMQ_PORT = "61616";
    //activeMQ的用户名
	private static final String ACTIVEMQ_USERNAME = "root";
	//activeMQ的密码
	private static final String ACTIVEMQ_PASSWORD = "123456";
	//连接工厂:JMS用它创建连接
	protected ConnectionFactory connectionFactory; 
	//JMS客户端到producer的连接
	protected Connection connection = null; 
	//会话,一个接收或者发送消息的线程
	protected Session session; 
	//消息的目的地,消息发送给谁
	protected Destination destination; 
	//消息生产者
	protected MessageProducer messageProducer; 	
	
	public ActiveMqPublisher(String topicName) {
		//ActiveMQ连接地址
		String brokerURL = "failover:(tcp://" + ACTIVEMQ_IP + ":" + ACTIVEMQ_PORT + ")" 
		//ActiveMQ重连机制,以保证继续正常工
		//initialReconnectDelay:默认为10,单位毫秒,表示第一次尝试重连之前等待的时间
		//maxReconnectDelay:默认30000,单位毫秒,表示两次重连之间的最大时间间隔
		        + "?initialReconnectDelay=1000&maxReconnectDelay=30000";  
		//实例化连接工厂
		connectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_USERNAME, ACTIVEMQ_PASSWORD, brokerURL);
		try {
			//通过连接工厂获取连接对象
			connection = connectionFactory.createConnection(); 
			 //启动连接
			connection.start();
			//创建Session,获取操作连接,第一个参数表示会话是否在事物中执行,第二个参数设定会话的应答模式
			session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE); 
			//创建消息队列,两种模式:Queue(队列)、Topic(主题)
			/*destination = session.createQueue(queueName);*/ 
			destination = session.createTopic(topicName);
			//创建消息生产者
			messageProducer = session.createProducer(destination); 
			log.info("创建ActiveMQ生产者成功")
		} catch (Exception e) {
			e.printStackTrace();
			log.error("创建ActiveMQ生产者失败:" + e.getMessage + e.getStackTrace, e);
		} 
	}
	
	/**
	 * 发送消息
	 * @param messageInfo
	 */
	public void sendMessage(String messageInfo) {
		try {
			//初始化一个mq消息
			TextMessage message = session.createTextMessage();
			//装载消息内容
			message.setText(messageInfo);
			//发送消息
			messageProducer.send(message);
		} catch (Exception e) {
			e.printStackTrace();
			log.error("ActiveMQ发送消息失败:" + e.getMessage + e.getStackTrace, e);
		} finally{
			if(connection!=null){
				try {
					connection.close();
				} catch (JMSException e) {
					e.printStackTrace();
					log.error("生产端ActiveMQ关闭连接失败:" + e.getMessage + e.getStackTrace, e);
				}
			}
		}	
	}
    
    public static void main(String[] args) {
    	ActiveMqPublisher activeMqPublisher = new activeMqProducer("topic");
    	activeMqPublisher.sendMessage("消息内容");
    }
}

ActiveMQ主题订阅者代码:

//1.监听器Listener
public class ActiveMqListener implements MessageListener {
	//日志对象
	private static Logger log = Logger.getLogger(ActiveMqListener.class);

	@Override
    public void onMessage(Message message) {
        try {
        	TextMessage textMessage = (TextMessage)message;
        	String jsonStr = textMessage.getText();
        	log.info("消费者消费的message:" + jsonStr);
        } catch (JMSException e) {
            e.printStackTrace();
            log.error("ActiveMQ消费异常:" + e.getMessage + e.getStackTrace, e);
        }
    }
}

//2.ActiveMQ主题订阅者
public class ActiveMqSubscribe {
	//日志对象
	private static Logger log = Logger.getLogger(ActiveMqProducer.class);
	//activeMQ的ip
    private static final String ACTIVEMQ_IP = "127.0.0.1";
    //activeMQ的端口,默认为61616
    private static final String ACTIVEMQ_PORT = "61616";
    //activeMQ的用户名
	private static final String ACTIVEMQ_USERNAME = "root";
	//activeMQ的密码
	private static final String ACTIVEMQ_PASSWORD = "123456";
	//连接工厂
	protected ConnectionFactory connectionFactory;
	//连接
	protected Connection connection = null;
	//会话
	protected Session session;
	//连接目的地
	protected Destination destination;
	//消息消费者
	protected MessageConsumer messageConsumer;
	
    public ActiveMqSubscribe(String topicName) {
    	//ActiveMQ连接地址
		String brokerURL = "failover:(tcp://" + ACTIVEMQ_IP + ":" + ACTIVEMQ_PORT + ")" 
		        + "?initialReconnectDelay=1000&maxReconnectDelay=30000"; 
        //实例化工厂
        connectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_USERNAME, ACTIVEMQ_PASSWORD, brokerURL);
        try {
        	//通过连接工厂获取连接对象
            connection = connectionFactory.createConnection();
            //启动连接
            connection.start();
            //创建Session,获取操作连接,第一个参数表示会话是否在事物中执行,第二个参数设定会话的应答模式
			session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE); 
			//创建消息队列,两种模式:Queue(队列)、Topic(主题)
			/*destination = session.createQueue(queueName);*/ 
			destination = session.createTopic(topicName);
			//创建消息消费者
			messageConsumer = session.createConsumer(destination);
            messageConsumer.setMessageListener(new ActiveMqListener());
            log.info("创建ActiveMQ消费者监听队列成功");
        } catch (JMSException e) {
            e.printStackTrace();
            log.error("创建ActiveMQ生产者失败:" + e.getMessage + e.getStackTrace, e);
        }finally {
              try {
                if (null != connection) {
                    connection.close();
                }
            } catch (JMSException e) {
                e.printStackTrace();
                log.error("消费端ActiveMQ关闭连接失败:" + e.getMessage + e.getStackTrace, e);
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值