三、消息协议及持久化机制

一、消息协议

1. 支持协议

  • docker/conf/activemq.xml中注明了所有的协议
  • 一般用的最多的是tcp协议和nio协议,其他协议不适合java

在这里插入图片描述

1. tcp协议:默认,性能相对可以,即openwire模式;
2. nio协议:更侧重于底层的访问,适用大量客户端连接activemq,底层为tcp协议,
           不过比tcp协议的性能更好
3. AMQP协议   STOP协议      MQTT协议     WS协议

2. NIO协议

  • 默认多协议访问,每个协议占用不同端口,各端口不能冲突
  • 当前是用docker,宿主机61617对应docker61616,因此将tcp的协议方式的端口暂时改为其他,nio的端口设置成了61616
  • 重启activemq
  • 新的nio的 url : nio://120.79.28.20:61617
<transportConnectors>
	<!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
	<transportConnector name="openwire" uri="tcp://0.0.0.0:61618?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
	<transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
	<transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
	<transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
	<transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
	<transportConnector name="nio" uri="nio://0.0.0.0:61616?trace=true"/>
</transportConnectors>

3. 单端口/多种协议

  • 上述配置只能使用单一协议匹配,待验证
  • 通过auto+nio,可以切换nio和tcp协议
  • url:tcp://60.205.229.31:61617 ==== nio://60.205.229.31:61617
  • 待验证
<transportConnectors>
	<!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
	<transportConnector name="openwire" uri="tcp://0.0.0.0:61618?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
	<transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
	<transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
	<transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
	<transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
	<transportConnector name="nio" uri="nio://0.0.0.0:61617?trace=true"/>
	<transportConnector name="auto+nio" uri="auto+nio://0.0.0.0:61616"/>
</transportConnectors>

二、持久化

  • 发送的持久化消息,会在activemq中持久化存储,保证数据的安全可靠性
  • 包含amq,kahadb,jdbc,levelDB等多种持久化方式;
#  发送步骤
1. 消息发送后,首先进行持久化, 再将消息发送给接收者消费;
2. 消费完成,则将持久化的文件删除掉
3. 消费失败,则继续尝试发送消费
4. 消息中心启动后,先去持久化文件查看是否存在未消费的,并进行推送消费

1. KahaDB

  • 当前版本的默认存储方式
  • 在conf/activemq/xml中进行了配置,日志最终目录: /data/activemq/kahadb
<persistenceAdapter>
    <kahaDB directory="${activemq.data}/kahadb"/>
</persistenceAdapter>
# 目录下的文件:4类文件和一把锁
db-6.log  db-7.log        db.data  db.redo  db.free  lock


1. db-6.log: 存储消息预定义文件,最大默认为32M,超出则新建一个文件
              当不再有引用到该文件的任何消息时候,将文件删除
              
2. db.data:   持久化消息的B树索引

3. db.free: 当前那些页面是空余的,具体内容是空余页面的ID

4. db.redo:进行消息恢复,用户B数索引的恢复

5. lock: 当前kahadb获取当前broker的读写权利

2. JDBC

2.1. mysql-connector-java的jar包上传至lib目录
# 1. jar包地址,选择与平台无关的zip文件,解压后即可得到对应的jar包
https://dev.mysql.com/downloads/connector/j/
# 2. 将jar包从Linux主机上拷贝到activemq的docker中的lib目录下(注意观察lib的全部路径名称)
docker cp /opt/mysql-connector-java-5.1.49.jar activemq:/opt/activemq/lib/
2.2. 修改conf/activemq.xml中的存储方式配置及及数据源
  • 默认dbcp2连接池,如要更换其他连接池,要把对应的jar包上传到lib目录下;
  • 需要在配置的对应数据库中,建一个名字为配置中的库名;
  • 修改完成后,重启activemq并确保其正常启动,就可以在对应数据库看到三张表已经自动创建了;
# 1. 先将docker中的activemq.xml拷贝到Linxu服务器的目录下方便修改
docker cp activemq:/opt/activemq/conf/activemq.xml /opt
# 2. 修改完成后再将其拷贝到docker的目录中去
docker cp /opt/activemq.xml activemq:/opt/activemq/conf/
# 3 坑爹点:
千万不要在activemq.xml中写中文注释,写了就报错了,坑爹;
<!--数据源从kahadb切换到musql-->
<persistenceAdapter> 
  <jdbcPersistenceAdapter dataSource="#mysql-ds" createTablesOnStartup="true"/> 
</persistenceAdapter>
</broker>
    <!--在broker标签外指定设置好的数据源,该数据源默认dbcp2作为连接池-->
      <bean id="mysql-ds" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close"> 
          <property name="driverClassName" value="com.mysql.jdbc.Driver"/> 
          <property name="url" value="jdbc:mysql://60.205.229.31:3307/activemq?relaxAutoCommit=true"/> 
          <property name="username" value="root"/> 
          <property name="password" value="123456"/> 
          <property name="poolPreparedStatements" value="true"/> 
      </bean> 
    <import resource="jetty.xml"/>
2.3. 对应表结构
  • 启动activemq后,自动创建三张表;
ACTIVEMQ_MSGS表:  用来存储队列消息,主题消息;

1. ID:             自增的数据库主键;
2. CONTAINER:      消息的Destination;
3. MSGID_PROD:     消息发送者的主键;
4. MSG_SEQ:       发送消息的顺序;  MSGID_PROD和MSG_SEQ组成JMS的MessageID;
5. EXPIRATAION:    消息的过期时间,存储的是1970-01-01到过期时间的毫秒数;
6. MSG:           消息本体的java 序列化对象的二进制数据;
7. PRIORITY:       优先级,从0-9,依次优先级升高;
ACTIVEMQ_ACKS:  用于存储订阅模式的相关数据,如果是持久化的发布订阅模式,保存在这个表中

1. CONTAINER:            消息的Destination;
2. SUB_DEST:              如果是使用static集群,这个字段会有其他集群的消息;
3. CLIENT_ID:             每个客户端都有唯一的ID来进行区分;
4. SUB_NAME:              订阅者的名称;
5. SELECTOR:              选择器,可以选择只满足一定条件的消息;
6. LAST_ACKED_ID:         记录消费过的消息的ID; 
 ACTIVEMQ_LOCK表:  这个表只有在集群模式下才有用,记录当前MASTER是哪个BROKER节点
1. TIME:              BROKER启动时候的时间;
2. BROKER_NAME:       当前master节点的broker的name
2.4 . 持久化过程
# 1. 持久化Queue
 - 消息发送后,先保存在ACTIVEMQ_MSGS表
 - 消息消费后,将ACTIVEMQ_MSGS表中删除
 - 非持久化下,消息只会保存在内存中

# 2. 非持久化topic
 - 数据保存在内存中
 - 消费者先启动,生产者后启动
 - 消费者关机了,该段时间内,生产者发布的消息其接受不到

# 3 持久化topic
- 消费者关机,该段时间生产者发布的消息,在消费者再次启动后,可以消费到
- 先启动消费者一次,再启动生产者
- 发布的所有消息,都会保存在ACTIVEMQ_MSGS表
- 消费后也不会进行删除(因为多个订阅者,删除了其他订阅者开机后就收不到)

3. JDBC With Journal存储

  • Jdbc,每次消息过来后都要进行读和写操作,效率慢
  • Jdbc前面用日志挡一层
  • 生产100条消息,短时间内消费了80条,那么只有剩下的20条才缓慢同步到jdbc中去,效率更高
3.1. activemq.xml的修改
  • 将之前的jdbc的配置方式删除,改为下面的方式,具体datasource的配置不变
<persistenceFactory>
   <journalPersistenceAdapterFactory 
          journalLogFiles="5" 
          journalLogFileSize="32768"
          useJournal="true"
          useQuickJournal="true"
          dataSource="#mysql-ds"
          dataDirectory="activemq-data"/>
 </persistenceFactory> 
3.2. 重启activemq
  • 现在的数据持久化的时候,先是保存到了日志中;
  • 如果短时间消费后,不再往数据库写,如果长时间没有消费(7-10分钟),才会写入到数据库中
4 . 其他方式
AMQ: 基于文件的存储方式,是以前版本的activemq的方式,现在已经弃用
levelDB: 采用文件存储的方式,性能更快,有望成为后续activemq的默认存储机制
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
AMQP(高级消息队列协议)提供了多种方式来保证消息持久化。下面是几种常见的方式: 1. 消息持久化:AMQP中的消息默认是非持久化的,也就是说,如果消息代理(broker)在将消息传递给消费者之前遇到故障,那么消息将会丢失。但是,AMQP允许将消息标记为持久化,这样即使代理在消息传递之前崩溃,消息也会被保存下来。在使用AMQP时,通常需要确保消息持久化的。 2. 消息确认:AMQP中的消费者可以使用基于确认的机制来确认它们已经成功地接收到一条消息。一旦消息被确认,代理就可以将其删除。如果消息尚未被确认,代理可能会将其重新传递给另一个消费者。这种机制可以确保消息不会丢失,因为如果代理在将消息传递给消费者之前崩溃,消息将被重新传递。 3. 消费者限流:AMQP中的消费者可以使用基于限流的机制来限制每次从代理接收的消息数量。这样可以确保代理不会向消费者发送太多消息,从而导致消费者无法及时处理所有消息。通过限制消费者接收的消息数量,可以确保代理不会过载,并保证消息的可靠性。 4. 消息备份:AMQP中的代理可以使用消息备份机制,将无法传递的消息备份到另一个代理。如果主代理在消息传递之前崩溃,备份代理可以接管消息传递的工作,从而保证消息的可靠性。 综上所述,AMQP提供了多种方式来保证消息的可靠传递和持久化。在使用AMQP时,可以根据具体的需求和情况选择适当的机制来保证消息的可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值