ActiveMQ架构及特性

kyaa111 3年前 ⋅ 784 阅读
架构
  1. 主从模式(Master Slave): JDBC方案 相较于集群, 该模式解决高可用的问题
    1. 在mq进程启动时一个master(某一台mq进程)获取数据库中表的独占锁,另一台mq进程会由于争抢不到表锁而阻塞,这样其它的进程都变成了slave。(只允许有一个master,可以有多个slave)
    2. 如果master的服务断开或者服务中断(比如进程中断、机器宕机等),它(原来的master)所占用的数据库表锁就会被释放,此时其他slave开始竞争锁,谁先抢到谁就是新的master, 若原来的master恢复了, 也因为获取不到锁而成为slave
    3. 客户端连接时, 可以通过以下方式保证服务可用
      1. 提前配置所有的mq服务地址
      2. 用配置的方式维护一个服务列表,每次连接时从列表上逐一尝试,当前连接超时后就顺序尝试下一个,如果某个服务成功就保存下来,防止每次都走这个重试流程
      3. 使用负载均衡软件,这样程序连接的地址是唯一的,故障转移由上述软件来完成即可。
  2. 集群(Broker Clusters): 相对于主从模式, 该模式可以进行负载均衡, 一个client1连接broker1发送消息,另一个client2连接broker2消费消息,这时就需要将broker1上的消息路由到broker2上。而当broker2上的consumer挂了,也需要将消息转发到其它的有consumer的broker上,避免消息大量堆积无法处理
  3. 同时使用主从和集群
传输模式
  1. 点对点传输: 一个生产者对应一个消费者, 生产者向broker推送数据, 数据存储在borker中, 点对点传输消费者可以接收到在连接之前生产者所推送的数据
  2. pub/sub: 订阅topic来接收相应数据,一个生产者可向多个消费者推送数据, 基于发布/订阅模式的传输方式消费者只能接收到连接之后生产者推送的数据
    1. 消息订阅分为非持久订阅和持久订阅
      1. 非持久订阅只有当客户端处于激活状态,也就是和JMS Provider保持连接状态才能收到发送到某个主题的消息,而当客户端处于离线状态,这个时间段发到主题的消息将会丢失,永远不会收到
      2. 持久订阅时,客户端向JMS注册一个识别自己身份的ID,当这个客户端处于离线时,JMS provider会为这个ID保存所有发送到主题的消息,当客户再次连接到JMS provider时,会根据自己的ID得到所有当自己处于离线时发送到主题的消息
发送策略
  1. 异步发送: 异步发送可能丢失消息, 因为消息可能还没到broker中, mq就宕机了, 此时异步消息都在生产者内存中, 所以需要设置异步回调
  2. 同步发送, 效率比异步稍低, 但更稳定
延时消息和定时消息
  1. 需要通过配置启用broker的功能
  2. 可以设置延时时间[DELAY], 重复投递次数[REPEAT], 重复投递间隔[PERIOD]
  3. 也可以直接使用cron表达式
  4. cron表达式的优先级高于另外三个参数,如果在设置了cron的同时,也有repeat和period参数,则会在每次cron执行的时候,重复投递repeat次,每次间隔为period。就是说设置是叠加的效果。例如每小时都会发生消息被投递10次,延迟1秒开始,每次间隔1秒
重试策略
  1. ActiveMQ中的消息重发,指的是消息可以被broker重新分派给消费者,不一定是之前的消费者
  2. 事务会话中,当还未进行session.commit()时,进行session.rollback(),那么所有还没commit的消息都会进行重发
  3. 使用客户端手动确认的方式时,还未进行确认并且执行Session.recover(),那么所有还没acknowledge的消息都会进行重发。
  4. 所有未ack的消息,当进行session.closed()关闭事务,那么所有还没ack的消息broker端都会进行重发,而且是马上重发.
  5. 消息被消费者拉取之后,超时没有响应ack,消息会被broker重发
  6. 重发指的是消息经过broker重新进行转发给消费者,经过测试,1和2的情况消息重发会发送给原来的消费者,3和4可以转发消息给别的消费者。累计次数超过设置的maximumRedeliveries时消息都会都会进入死信队列
  7. 消息的重发时间间隔和重发次数, 间隔 1 次数 6 (6次之后进入死信队列)
可靠性机制
  1. 消息接收确认, 消息只有在被确认之后, 才认为已经被成功地消费了, 消息的成功消费通常包含三个阶段:客户接收消息、客户处理消息和消息被确认. 在事务性会话中,当一个事务被提交的时候, 确认自动发生
    1. Session.AUTO_ACKNOWLEDGE:当客户成功的从receive方法返回的时候,或者从MessageListener.onMessage方法成功返回的时候,会话自动确认客户收到的消息
    2. Session.CLIENT_ACKNOWLEDGE:客户通过调用消息的acknowledge方法确认消息。需要注意的是,在这种模式中,确认是在会话层上进行,确认一个被消费的消息将自动确认所有已被会话消费的消息。例如,如果一个消息消费者消费了10个消息,然后确认了第5个消息,那么所有10个消息都被确认
    3. Session.DUPS_ACKNOWLEDGE:该选择只是会话迟钝的确认消息的提交。如果JMS provider失败,那么能会导致一些重复的消息。如果是重复的消息,那么JMS provider必须把消息头的JMSRedelivered字段设置为true。
  2. 消息持久性,JMS支持以下两种消息提交模式:
    1. PERSISTENT:指示JMS provider持久保存消息,以保证的消息不会因为JMS provider的失败而丢失
    2. NON_PERSISTENT:不要求JMS provider持久保存消息
  3. 消息优先级 可以使用消息优先级别来指示JMS provider首先提交紧急的消息。优先级分10个级别,从0(最低)到9(最高). 如果不指定优先级,默认级别是4。需要注意的是,JMS provider并不一定保证接照优先级的顺序提交消息
  4. 顺序消息, 保证消息在多个consumer的消费顺序
  5. 消息过期,可以设置消息在一定时间后过期,默认是永不过期
  6. 消息的临时目的地,可以通过会话上的createTemporaryQueue方法和createTemporaryTopic 方法来创建临时目的地。它们的存在时间只限于创建它们的连接所保持的时间。 只有创建临时目的地的连接上的消息消费者才能够从临时目的地中提取消息
  7. 持久订阅 首先消息生产者必须使用PERSISTENT提交消息。客户可以通过会话上的 createDurab1eSubscriber方法来创建一个持久订阅,该方法的第一个参数必须 是一个topic。第二个参数是订阅的名称。JMS provider会存储发布到持久订阅对应的topic上的消息。如果最初创建 持久订阅的客户或者任何其它客户,使用相同的连接工厂和连接的客户ID,相同的主题和相同的到订阅名,再次调用会话上的createDurab1eSubscriber方法,那么持久订阅就会被激活。JMS provider会向客户发送客户处于非激活状态时所发布的消息。持久订阅在某个时刻只能有一个激活的订阅者。持久订阅在创建之后会一直保留,直到应用程序调用会话上的unsubscribe方法
  8. 本地事务 在一个JMS客户端,可以使用本地事务来组合消息的发送和接收。JMS Session接口提供了commit和rollback方法。事务提交意味着生产的所有消息被发送,消费的所有消息被确认;事务回滚意味生产的的所有消息被销毁,消费的所有消息被恢复并重新提交,除非它们已经过期. 事务性的会话总是牵涉到事务处理中,commit或rollback方法一旦被调用,一个事务就结束了,而另一个事务被开始。关闭事务性会话将回滚其中的事务。得要注意的是,如果使用请求/回复机制,即发送一个消息,同时希望在同一个事务中等待接收该消息的回复,那么程序将被挂起,因为知道事务提交,发送操作才会真正执行 需要注意的还有一个,消息的生产和消费不能包含在同一个事务中
消息存储方式
  1. AMQ消息存储一基于文件的存储方式,是以前的默认消息存储
  2. KahaDB消息存储一提供了容量的提升和恢复能力,是现在的默认存储方式, 消息存储使用一个事务日志和仅仅用一个索引文件来存储它所有的地址, KahaDB是一个专门针对消息持久化的解决方案,它对典型的消息使用模式进行了优化。在Kaha中,数据被追加到datalogs中。当不再需要log文件中的数的时候,log文件会被丢弃。
  3. JDBC消息存储一消息基于JDBC存储的
  4. Memory消息存储一基于内存的消息存储
Destination特性
  1. 通配符
  2. 组合队列, 允许用一个虚拟的destination代表多个destinations。这样就可以通过composite destinations在一个操作中同时向多个queue发送消息
  3. 自动删除删除不活动的Destinations
  4. 虚拟Destinations, 解决消费者不能分组消费消息
  5. 镜像队列