ActiveMQ 简介
Apache 下的开源消息队列中间件
功能
- ActiveMQ 是消息队列技术,为解决高并发问题而生
- ActiveMQ 生产者消费者模型(生产者和消费者可以跨平台、跨系统)
- ActiveMQ 支持如下两种消息传输方式
a.点对点模式,生产者生产了一个消息,只能由一个消费者进行消费
b.发布/订阅模式,生产者生产了一个消息,可以由多个消费者进行消费
基本概念
ActiveMQ 支持两种消息队列模式
- 点对点(point to point, queue)
- 发布/订阅(publish/subscribe,topic)
两者最大的差别在于 是否能重复消费
Queue
点对点:Queue,不可重复消费
消息生产者生产消息发送到 queue 中,然后消息消费者从 queue 中取出并且消费消息。
消息被消费以后,queue 中不再有存储,所以消息消费者不可能消费到已经被消费的消息。
Queue 支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费、其它的则
不能消费此消息了。
当消费者不存在时,消息会一直保存,直到有消费者消费
Topic
发布/订阅:Topic,可以重复消费
消息生产者(发布)将消息发布到 topic 中,同时有多个消息消费者(订阅)消费该消息。
和点对点方式不同,发布到 topic 的消息会被所有订阅者消费。
当生产者发布消息,不管是否有消费者。都不会保存消息
Jms 规范里的两种 message 传输方式 Topic 和 Queue,两者的对比如下表:
安装(docker)
基于 dockers 的容器化搭建,前提主机安装 docker
搜索镜像
docker search activemq
下载镜像
docker pull webcenter/activemq
查看镜像
docker images
启动容器
docker run -d --name activemq -p 61616:61616 -p 8161:8161 docker.io/webcenter/activemq
映射端口 61616, 8161
测试
http://ip:8161/admin/
默认密码 admin
如下为启动成功
查看 queue
队列消息名,队列中的待处理消息数,消费者数量,历史消息数,历史处理消息数
查看 topic
发布的消息名,消费者数量,历史消息数,收到发布消息的数量
JAVA API 操作
样例为 springboot 下整合 activemq,将商品信息同步索引库的消息塞入 queue 中,使用点
对点的方式处理消息
pom 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
//topic 模式
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
<version>5.15.0</version>
</dependency>
application.yml 配置
spring:
activemq:
broker-url: tcp://172.16.23.195:61616
Java 代码
消息生产者
创建一个同步索引的消息,并将消息塞入 queue 队列
@Autowired
private JmsTemplate jmsTemplate;
private Destination destination;
destination = new ActiveMQQueue("item.sync");
jmsTemplate.send(destination, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
TextMessage textMessage =
session.createTextMessage(type+","+String.valueOf(id));
return textMessage;
}
});
消息消费者
// 使用 JmsListener 配置消费者监听的队列,其中 message 是接收到的消息
@JmsListener(destination = "item.sync")
public void onMessage(Message message) {
try {
//从消息中取商品 id
TextMessage textMessage = (TextMessage) message;
log.info("得到消息:"+textMessage.getText());
String[] text = textMessage.getText().split(",");
Long itemId = new Long(text[1]);
//等待事务提交
Thread.sleep(1000);
//更新索引
....业务代码
实现效果
先去前台查询商品,我们输入 r,但是没有查到任何商品
编辑商品,修改了某个商品名,增加了 r 这个字母
编辑商品后调用消息生产者往queue里插入消息,将新的商品名索引同步消息插入,pending
message 和 enqueued 都有新增
等一会再刷新页面,发现 pending 为 0,dequeued 增加到和 enqueued 相同,说明队列消
息已经被消费者处理完成
再查询前台可以看到索引库更新成功