消息中间件activeMQ原理和使用

  • Post author:
  • Post category:其他



一: 消息中间件的优势


1.使用消息中间件,降低了dubbo服务之间的耦合度,使得两个原本使用远程注入耦合了的模块可以实现松耦合,使用消息中间件进了间接通信.

2.缓冲能力,消息中间件就像一个巨大的蓄水池,将高峰期的大量请求存储起来交给后台慢慢处理,对于秒杀业务尤其重要.


二: 消息中间件的两种消息传递模式


1.点对点消息通信型:也称为队列模式,一条特定的消息只给一个特定的消费者,消费完成之后就从持久化存储中删除该数据,生产者将消息发送到指定的队列(queue)中,此时对于消费者来说,获取消息有两种方式.分别是pull和push,其中push方式是activeMQ接收到消息之后去调用消费者的新消息通知接口,相当于activeMQ去通知消费者,但是这样会浪费activeMQ的宝贵线程资源.而pull方式,是消费者循环调用activeMQ的api去获取消息,这样不会消耗activeMQ的线程资源,并且消费者更加主动.push方式由于过多占用activeMQ的线程资源而难以应对高并发,所以并不适用.

2.发布/订阅模式:也称为主题模式,特定的一条消息可以被多个消费者接收,只要消费者订阅了某个主题.消息的生产者会将消息发布到名称为topic的虚拟通道里面去,topic是可以被多个消费者订阅的.这个模式类似于广播模式,但是要求消费者在线监听,如果消费者离线,再次上线是无法获取该消息的,发布/订阅模式采用的是pull方式把消息发送给消费者.


三:两种消息传递模式的配置和使用


1.点对点消息通信型的举例

需求描述:电商系统的商家后台系统,审核商品之后,需要把经过审核的商品的信息同步到solr索引库中,此时商家后台工程和搜索服务(导入solr索引库)之间是耦合的,因为商家后台工程依赖了搜索服务.当商家后台执行了审核方法之后,向activeMQ发送消息,然后搜索服务activeMQ接收消息并更新索引库,因为导入solr索引库只需要执行一次,然后所有的服务就都可以使用,所以使用一对一的消息队列接口.


生产信息

:此时,商家后台系统作为生产者,而搜索服务作为消费者.发送消息的步骤:

1.在pom文件中,如果商家后台系统依赖了了搜索服务,我们需要把依赖删除.然后引入jms和activeMQ的依赖

2.编辑配置文件,配置工厂类等信息不再叙述,在web.xml中加载此配置文件,因为都是一样的,而队列消息的目的地配置如下图所示

在这里插入图片描述

3.在商家后台系统里面审核方法里面编程,首先注入队列消息的目的地对象Destination,其名称就是我们在上图中配置的id,通过id找到这个指定的bean

4.然后使用jms模板jmsTemplate调用send方法,以指定数据格式发送数据到activeMQ.

if(status.equals("1")) {
//调用方法获取集合
List<TbItem> list = goodsService.findItemListByGoodsIdandStatus(ids, status);
//判断,如果获取的集合的长度大于0
if(list.size()>0) {
	//将list集合转换成json字符串发送
	final String jsonString = JSON.toJSONString(list);
	//调用send方法发送
	jmsTemplate.send(queueSolrDestination, new MessageCreator() {
		@Override
		public Message createMessage(Session session) throws JMSException {
			return session.createTextMessage(jsonString);
		}
	});
}


消费信息

:此时,搜索服务作为消费者来获取activeMQ里面的数据,然后做存入索引库的操作,步骤如下:

1.在搜索服务中然后引入jms和activeMQ的依赖

2.编辑配置文件,在web.xml中加载此配置文件,下图是消费者配置文件的需要修改的地方,如果还有其他操作把这两份配置复制一下即可

在这里插入图片描述

3.在搜索服务下定义一个监听器类,名称和上述配置文件中的name=messageListener的属性的引用itemSearchListener相同,首字母改大写,实现MessageListener接口,加上@Component注解.

4.在重写的onMessage方法里面,获取activeMQ里面传递的数据,然后注入搜索服务,此时就是在同一个工程之类注入,可以做到高内聚,调用搜索服务的方法导入到solr索引库.

@Component
public class ItemSearchListener implements MessageListener {
	@Autowired
	private ItemSearchService itemSearchService;
	@Override
	public void onMessage(Message messgae) {
		TextMessage textMessage=(TextMessage)messgae;
		String text;
		try {
			//获取内容
			text = textMessage.getText();
			//将text转换成集合
			List<TbItem> list=JSON.parseArray(text,TbItem.class);
			//调用importList方法,导入到solr索引库
			itemSearchService.importList(list);
		} catch (JMSException e) {
			e.printStackTrace();
		}
	}
}

2.发布/订阅模式的举例

需求描述:电商系统的商家后台系统,审核商品之后,需要把审核的商品的id传递给页面服务,由页面服务使用freemarker生成一个个的商品静态页面,消息中间件activeMQ实现运营商后台和页面生成服务之间的松耦合,商家后台审核之后,向activeMQ发送消息(审核通过的商品的id数组),然后页面生成服务接收activeMQ的消息,执行商品详情页的生成操作.我们搭建的多台服务器上,每一台服务器上都有相同的页面,也就是说这里的消息生产者(运营商服务)和消息消费者(页面服务)之间是发布订阅的关系,运营商服务发布消息,多个服务器(页面服务)订阅该消息,然后执行生成静态页面的操作.


生产信息

:商家后台系统作为消息的生产者,需要把审核的商品的id的数组发送到activeMQ里面去.步骤如下:

1.在pom文件中,如果商家后台系统依赖了了页面服务,我们需要把依赖删除.然后引入jms和activeMQ的依赖

2.编辑配置文件,配置工厂类等信息不再叙述,在web.xml中加载此配置文件,因为都是一样的,而发布/订阅消息的目的地配置如下图所示

在这里插入图片描述

3.在商家后台系统里面审核方法里面编程,首先注入队列消息的目的地对象,Destination,其名称就是我们在上图中配置的id,通过id找到这个指定的bean.

4.然后使用jms模板jmsTemplate调用send方法,已指定数据格式发送数据到activeMQ

for(final Long id:ids) {
	//itemPageService.genItemHtml(id);
	jmsTemplate.send(topicPageDestination, new MessageCreator() {
		@Override
		public Message createMessage(Session session) throws JMSException {
			//将id以文本形式传递到activeMQ
			return session.createTextMessage(id+"");
		}
	});
}


消费消息

:页面服务作为消息的消费者,从activeMQ里面获取数据,根据数据调用服务层方法完成页面生成的操作.

1.在页面服务中然后引入jms和activeMQ的依赖

2.编辑配置文件,在web.xml中加载此配置文件,下图是消费者配置文件的需要修改的地方,如果还有其他操作把这两份配置复制一下即可

在这里插入图片描述

3.在搜索服务下定义一个监听器类,名称和上述配置文件中的name=messageListener的属性的引用pageDeleteListener相同,首字母改大写,实现MessageListener接口.

4.在重写的onMessage方法里面,获取activeMQ里面传递的数据,然后注入页面服务,此时就是在同一个工程之类注入,可以做到高内聚,调用页面服务的方法创建静态页面.

@Component
public class PageListener implements MessageListener {
	@Autowired
	private ItemPageService itemPageService;
	@Override
	public void onMessage(Message message) {
		//强制转换
		TextMessage textMessage= (TextMessage)message;
		try {
			//获取内容
			String text = textMessage.getText();
			//调用服务层方法,创建商品页面
			itemPageService.genItemHtml(Long.parseLong(text));
		} catch (JMSException e) {
			e.printStackTrace();
		}
	}
}


四 :配置的时候,配置队列模式还是发布/订阅模式,他的区别在于:


在这里插入图片描述



版权声明:本文为weixin_44497110原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。