首先,说起ActiveMQ,就必须先聊聊JMS(Java Message Service)规范,也就是Java消息服务,它定义了Java中访问消息中间件的接口的规范。JMS只是接口,并没有给予实现,实现JMS接口的消息中间件称为 “JMS Provider”,目前知名的开源 MOM (Message Oriented Middleware,也就是消息中间件)系统包括Apache的ActiveMQ、RocketMQ、Kafka,以及RabbitMQ,可以说他们都 “基本遵循” 或 “参考” JMS规范,都有自己的特点和优势。
mq能解决什么问题:
异步:调用者无需等待
解耦:解决系统之间的耦合调用
削峰:抵御洪峰流量,保护核心业务
activemq的简单介绍:
activemq有两种模式,一种是queue模式,一种的topic模式。queue模式的消息默认是持久化的,被消费者消费完就没了,一个消息只能被一个消费者消费。topic是一种主题订阅模式,消费者需要先订阅一个topic,然后消息出现了才会发送给订阅者,如果没有订阅者,消息会被丢弃。
五种消息格式
typeMessage、StreamMessage、TextMessage、ObjectMessage、MapMessage
传输协议
activemq支持很多种的传输协议,默认是使用http协议,可以更改为nio协议提升activemq传输性能
持久化
queue默认是持久化的,topic默认不是
底层实现:
kahadb:
包含四个文件: db.data da.free db.redo lock
大致流程:消息以追加的形式加到db-< number>.log文件中,如果文件满了,就新建一个log文件(默认最大大小为32M),同时number + 1。db.data存的是btree索引,指向log文件,如果一个log文件没有引用了,就会被归档或者删除
db.data:btree索引,指向log文件。维护了一个FIFO队列,消息被消费后就出队(被移除)
db.free:表示哪些文件是空的
db.redo:在一次硬件停机之后,用来进行消息恢复Btree索引。
lock:表示获得的锁的broker
jdbc存储
有三个表,activemq-msgs:用于放消息,queue和topic都存放在这里
ID:自增的数据库主键
CONTAINER:消息的Destination
MSGID_PROD:消息发送者客户端的主键
MSG_SEQ:是发送消息的顺序,MSGID_PROD+MSG_SEQ可以组成JMS的MessageID
EXPIRATION:消息的过期时间,存储的是从1970-01-01到现在的毫秒数
MSG:消息本体的Java序列化对象的二进制数据
PRIORITY:优先级,从0-9,数值越大优先级越高
activemq-acks:订阅者和服务器的关系放在这里表里
CONTAINER:消息的Destination
SUB_DEST:如果是使用Static集群,这个字段会有集群其他系统的信息
CLIENT_ID:每个订阅者都必须有一个唯一的客户端ID用以区分
SUB_NAME:订阅者名称
SELECTOR:选择器,可以选择只消费满足条件的消息。条件可以用自定义属性实现,可支持多属性AND和OR操作
LAST_ACKED_ID:记录消费过的消息的ID。
activemq-lock:获取了锁的broker,集群环境下生效
LevelDB
目前已经被不推荐使用的
The main reason is that KahaDB continues to be the main focus where bugs are fixed and not much attention is paid to LevelDB. There seems to be several issues with corruption (especially with replication) so I don’t think it should be a recommended store unless the stability is sorted out. Unfortunately nearly every JIRA reported against LevelDB goes ignored.
大概意思是:KahaDB仍然是BUG修复的主要关注点,并且没有对LevelDB给予太多关注。它似乎有一些问题(特别是在replication),所以并不推荐它作为存储方式,除非稳定性能够得到保证。
没啥了解,以后在补充吧。。。
activemq有几种通信方式?
publish(发布)-subscribe(订阅)(发布-订阅方式)
如何解决消息重复问题?
所谓消息重复,就是消费者接收到了重复的消息,一般来说我们对于这个问题的处理要把握下面几点,
①.消息不丢失(上面已经处理了)
②.消息不重复执行
一般来说我们可以在业务段加一张表,用来存放消息是否执行成功,每次业务事物commit之后,告知服务端,已经处理过该消息,这样即使你消息重发了,也不会导致重复处理
大致流程如下:
业务端的表记录已经处理消息的id,每次一个消息进来之前先判断该消息是否执行过,如果执行过就放弃,如果没有执行就开始执行消息,消息执行完成之后存入这个消息的id
ActiveMQ消息发送失败?
丢消息怎么办?