• 基于Networks of Brokers的HA方案


    上一篇介绍了基于ZK的ActiveMQ HA方案,虽然理解起来比较容易,但是有二个不足:

    1)  占用的节点数过多,1个zk集群至少3个节点,1个activemq集群也至少得3个节点,但其实正常运行时,只有一个master节点在对外响应,换句话说,花6个节点的成本只为了保证1个activemq master节点的高可用,太浪费资源了。

    2)  性能下降太明显,比起单节点的activemq,性能下降了近1个数量级。

    这一篇将介绍基于networks of brokers的HA方案,不需要借助zk等第3方组件,只需要2个activemq节点就能达到类似效果,进入正题之前,先来简单谈谈Broker这个概念。

    Broker一词的原意是『经纪人、中间人』,用在ActiveMQ的构架中,即:Broker 作为Producer与Consumer的中间人(或代理人),生产者不用知道消费者在哪里、如何消费这些细节,只要将消息扔给中间人Broker即可, 类似的,消费者也不用关心消息是从哪个生产者过来的,它只知道这是从Broker那里拿来的,如果画一张图来描述,就是下面这样(引用自本文最后参考文章 中的图片)

     

    那么,当生产者将消息发给Broker时,会发生什么?下图描述的就是这个过程:

    1) 生产者将消息发给Broker

    2) Broker将消息落地存储

    3) 然后给生产者反馈:事情我已经办妥了!

    继续,再来看看消费者又是如何跟Broker打交道的:

    1) Broker将接收到的消息,从db中取出

    2) 然后发送给消费者

    3) 如果消费者使用的是自动确认模式(即:Session.AUTO_ACKNOWLEDGE),则Consumer会马上告诉Broker:ok,消息我已经收到了。

    4) 然后进行自己的业务处理

    5) Broker一旦收到确认,将会马上更新消息的状态为已消费(或直接删除,取决于持久化的实现机制)(注:虽然图中步骤5排在步骤4之后,但是步骤4、5几乎是同时发生的)

    在一些大型应用中,如果一个Broker出现性能瓶颈抗不住压力,可能会拆分成多个Broker,如下图所示:

    (注:上图中箭头的方法并非数据流向,而应该理解成调用关系,即:Producer调用Broker1,Consumer调用Broker2...)

    Producer将消息发送给Broker1,而Consumer从另一个Broker2接收消息,有点类似数据库读写分离的意思,这样系统的性能 可以提升一定程度的提升,但是问题来了,Broker1上的消息,如何同步到Broker2呢,这就依赖networkConnector的配置。

    复制代码
     1 <beans
     2         xmlns="http://www.springframework.org/schema/beans"
     3         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
     5   http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
     6 
     7   <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
     8     <property name="locations">
     9       <value>file:${activemq.conf}/credentials.properties</value>
    10     </property>
    11   </bean>
    12 
    13   <broker xmlns="http://activemq.apache.org/schema/core" brokerName="activemq-1">
    14     <networkConnectors>
    15       <networkConnector uri="static:(tcp://127.0.0.1:61626)"/>
    16     </networkConnectors>
    17     <persistenceAdapter>
    18       <kahaDB directory="${activemq.data}/kahadb"/>
    19     </persistenceAdapter>
    20     <transportConnectors>
    21       <transportConnector name="openwire"
    22                           uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
    23     </transportConnectors>
    24   </broker>
    25 
    26   <import resource="jetty.xml"/>
    27 </beans>
    复制代码

    注意:14-16行及21-22行,该Broker对外暴露61616端口,同时"连接"到61626端口(即另1个broker),最终的效果相当于,如果有producer把消息发到61616(broker1),则从另一个broker(61626端口)上也能消费这条消息。

    明白这些基本原理后,在61626对应的activemq上,也做类似的配置,只不过"连接方向"正好相反,参考以下配置:

    复制代码
     1 <beans
     2         xmlns="http://www.springframework.org/schema/beans"
     3         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
     5   http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
     6 
     7     <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
     8         <property name="locations">
     9             <value>file:${activemq.conf}/credentials.properties</value>
    10         </property>
    11     </bean>
    12 
    13     <broker xmlns="http://activemq.apache.org/schema/core" brokerName="activemq-2">
    14         <networkConnectors>
    15             <networkConnector uri="static:(tcp://127.0.0.1:61616)"/>
    16         </networkConnectors>
    17         <persistenceAdapter>
    18             <kahaDB directory="${activemq.data}/kahadb"/>
    19         </persistenceAdapter>
    20         <transportConnectors>
    21             <transportConnector name="openwire"
    22                                 uri="tcp://0.0.0.0:61626?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
    23         </transportConnectors>
    24     </broker>
    25 
    26     <import resource="jetty.xml"/>
    27 </beans>
    复制代码

    (注:如果希望2个activemq上都能访问admin管理界面,jetty.xml中的端口要修改,不要冲突)

    这样,activemq-1与activemq-2这二个broker就互为主备,发给你的消息会同步到我,发给我的消息也会同步到你,实现了HA,示意图如下:

    Producer与Consumer连接到activemq时,配置文件可以这么写:

    复制代码
    1 <bean id="jmsFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop">
    2     <property name="connectionFactory">
    3         <bean class="org.apache.activemq.ActiveMQConnectionFactory">
    4             <!--broker服务的地址-->
    5             <property name="brokerURL" value="failover:(tcp://localhost:61616,tcp://localhost:61626)"/>
    6             ...
    7         </bean>
    8     </property>
    9 </bean>
    复制代码

    这种HA方案的优点是占用的节点数更少(只需要2个节点),而且2个broker都可以响应消息的接收与发送,性能比zookeeper方案要好一些。

    最后,再给一个简化配置的技巧,以上述的2节点HA方案中,二个activemq的配置文件都要加networkConnector配置,如果想减轻配置的工作量,也可以只在其中一个activemq设置,参考以下片段:

        <networkConnectors>
          <networkConnector uri="static:(tcp://127.0.0.1:61626)" duplex="true"/>
        </networkConnectors>

    即:在61616这个activemq的配置文件中,添加networkConnector时,增加duplex="true",也就是双工通讯的意思,这样61616与61626这二个activemq上的broker就建立了双向通讯连接,另一个activemq上就无需额外配置了(注:如果在61626上配置了,反而会报错)

    参考文章:

    http://www.jakubkorab.net/2011/11/understanding-activemq-broker-networks.html

    http://activemq.apache.org/networks-of-brokers.html

  • 相关阅读:
    springboot sql注解拦截器
    springboot+shiro登录校验及权限验证
    springboot全局异常拦截器
    asp.netMVChtml.ActionLink的⼏种参数格式
    uniapp操作笔记
    asp.net mvc传参
    asp.net mvc上传视频
    Asp.net core 文件上传和保存
    asp.net mvc View渲染顺序
    SpringBoot项目多个启动类模块之间相互调用
  • 原文地址:https://www.cnblogs.com/qiumingcheng/p/5378629.html
Copyright © 2020-2023  润新知