title: Activemq集群部署 #标题tags: mq #标签
date: 2020-08-12
categories: MQ # 分类

Activemq默认使用kahaDB持久化方式,但在5.9以上ActiveMQ版本,可利用zookeeper+levelDB的方法,此方法利用zookerper控制broker的主从,每个节点有自己的一个levelDB模式的存储文件,3节点activemq集群的情况下每次发送和消费只有当2个activemq都完成更新的时候才算成功,当master节点挂掉的时候会控制最新更新的一个broker节点成为新的master。

此文章部署的activemq版本为5.16.0。
补充1:在我浏览levedb相关文档时,发现官方文档中有如下提示(我想静静):

Activemq集群部署 - 图1

补充2:注意事项

LevelDB存储尚不支持存储与Delay和Schedule Message Delivery相关的数据。这些存储在单独的非复制KahaDB数据文件中。如果将“延迟”和“计划消息传递”与复制的leveldb存储一起使用,则会发生意外结果,因为当主服务器故障转移到从服务器时,该数据将不存在。

Activemq集群部署方案比较

摘自:ActiveMq 集群部署 三种方案 + 负载均衡+其他细节点

存储及性能比较

默认的单机部署(kahadb)

activeMQ的默认存储的单机方式,以本地kahadb文件的方式存储,所以性能指标完全依赖本地磁盘IO,不能提供高可用。

基于zookeeper的主从(levelDB Master/Slave)

5.9.0新推出的主从实现,基于zookeeper来选举出一个master,其他节点自动作为slave实时同步消息。
因为有实时同步数据的slave的存在,master不用担心数据丢失,所以leveldb会优先采用内存存储消息,异步同步到磁盘。所以该方式的activeMQ读写性能都最好,特别是写性能能够媲美非持久化消息。

优点:
1、实现高可用和数据安全。
2、性能较好。

缺点:
1、 因为选举机制要超过半数,所以最少需要3台节点,才能实现高可用。

基于共享数据库的主从(Shared JDBC Master/Slave)

可以基于postgres、mysql、oracle等常用数据库。
每个节点启动都会争抢数据库锁,从而保证master的唯一性,其他节点作为备份,一直等待数据库锁的释放。
因为所有消息读写,其实都是数据库操作,activeMQ节点本身压力很小,性能完全取决于数据库性能。

优点:
1、实现高可用和数据安全
2、简单灵活,2台节点就可以实现高可用
缺点:
1、稳定性依赖数据库
2、性能依赖数据库

灾备方案比较

leveldb方式

需要3台节点,2台在主机房,1台在备机房,主机房的节点权重设的比备机房节点高。
当master节点故障:
因为权重的关系,主机房另一个节点会自动被选举为新的master。
当主机房故障:
需要启动备用机房时,先更改备机房节点配置,把集群规模从3改成1,这样1个节点可以临时提供服务(此时不再保证高可用)。

共享数据库方式

3台节点即可,2台在主机房,1台在备机房,备机房节点指向灾备activeMQ数据库,平时要关闭。
当master节点故障:
主机房的另一个节点会自动取得数据库锁,成为新的master。
当主机房故障:
需要启动备用机房时,先完成activeMQ数据库的切换,然后启动灾备activeMQ节点即可临时外提供服务(此时不再保证高可用)。

好了,废话不多说,开始部署

环境准备

OS hostname IP service Port
Centos 7.5 amq1 192.168.20.2 zookeeper、activemq 62621(集群端口)、61616(消息端口)、8161(管控台端口)
Centos 7.5 amq2 192.168.20.3 zookeeper、activemq 62621(集群端口)、61616(消息端口)、8161(管控台端口)
Centos 7.5 amq3 192.168.20.4 zookeeper、activemq 62621(集群端口)、61616(消息端口)、8161(管控台端口)

部署zookeeper集群

配置java环境

所有机器都需配置。

自行去oracle官网下载java包,然后上传至各个服务器。

  1. # 配置jdk环境(jdk版本不可过高,已验证jdk 14会在activemq启动后无法连接到zookeeper)
  2. $ tar zxf jdk-8u261-linux-x64.tar.gz -C /opt/
  3. $ ln -sf /opt/jdk1.8.0_261 /opt/jdk
  4. $ cat >> /etc/profile << EOF
  5. export JAVA_HOME=/opt/jdk
  6. export CLASSPATH=\$JAVA_HOME/lib
  7. export PATH=\$JAVA_HOME/bin:\$PATH
  8. EOF
  9. $ source /etc/profile
  10. $ $ java -version # 查看版本信息
  11. java version "1.8.0_261"
  12. Java(TM) SE Runtime Environment (build 1.8.0_261-b12)
  13. Java HotSpot(TM) 64-Bit Server VM (build 25.261-b12, mixed mode)

部署zookeeper

以下操作在amq1配置即可。

  1. # 下载
  2. cd /opt/
  3. wget https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/zookeeper-3.6.2/apache-zookeeper-3.6.2-bin.tar.gz
  4. tar zxf apache-zookeeper-3.6.2-bin.tar.gz
  5. ln -sf /opt/apache-zookeeper-3.6.2-bin /opt/zk
  6. # 配置
  7. cd /opt/zk/conf/
  8. mkdir /opt/zk/data
  9. echo 1 > /opt/zk/data/myid
  10. $ cat /opt/zk/conf/zoo.cfg # 编写配置文件如下
  11. dataDir=/opt/zk/data
  12. clientPort=2181
  13. maxClientCnxns=0
  14. tickTime=2000
  15. initLimit=10
  16. syncLimit=5
  17. quorumListenOnAllIPs=true
  18. server.1=192.168.20.2:2888:3888
  19. server.2=192.168.20.3:2888:3888
  20. server.3=192.168.20.4:2888:3888
  21. # 将zookeeper目录发送至其他节点
  22. $ for i in `seq 3 4`;do rsync -az /opt/apache-zookeeper-3.6.2-bin 192.168.20.${i}:/opt/;done
  23. # 启动192.168.20.2节点的zookeeper
  24. $ /opt/zk/bin/zkServer.sh --config /opt/zk/conf start
  25. # 只有leader才会监听28888
  26. ss -lnpt | egrep '2181|3888|2888'

修改amq2节点的配置文件

  1. ln -sf /opt/apache-zookeeper-3.6.2-bin/ /opt/zk
  2. echo 2 > /opt/zk/data/myid

修改amq3节点的配置文件

  1. ln -sf /opt/apache-zookeeper-3.6.2-bin/ /opt/zk
  2. echo 3 > /opt/zk/data/myid

执行以下指令启动各个zookeeper节点

  1. /opt/zk/bin/zkServer.sh --config /opt/zk/conf start
  2. ss -lnpt | egrep '2181|3888|2888' # 确定端口在监听
  3. # 别忘了,只有leader才会监听2888

验证zookeeper集群状态

如何查看Zookeeper中的数据呢,我们可以通过ZkCli.sh命令客户端查看,但是不太直观,因为ZK本身数据是以树型结构存储组织的,所以这里推荐一个实用的界面操作工具——ZooInspector。

1、下载 https://issues.apache.org/jira/secure/attachment/12436620/ZooInspector.zip;

2、运行zookeeper-dev-ZooInspector.jar

  • 解压,进入目录ZooInspector\build。
  • 在build目录,按住shift键右键鼠标,在右键菜单出选择“在此处打开powershell窗口”。
  • 执行命令 java -jar .\zookeeper-dev-ZooInspector.jar

执行成功后,会弹出java ui client。如下:

Activemq集群部署 - 图2

点击上面箭头所示,然后输入zookeeper连接信息,如下:

Activemq集群部署 - 图3

既可看到集群相关信息,如下:

Activemq集群部署 - 图4

至此,zookeeper集群部署完成。

部署activemq集群

部署amq1

接下来的操作只需要在amq1这台机器执行。

  1. # 下载及解压
  2. $ wget https://mirrors.tuna.tsinghua.edu.cn/apache/activemq/5.16.0/apache-activemq-5.16.0-bin.tar.gz
  3. $ tar zxf apache-activemq-5.16.0-bin.tar.gz -C /opt/
  4. $ ln -sf /opt/apache-activemq-5.16.0 /opt/activemq
  5. $ cd /opt/activemq/
  6. ########### 配置与优化 ###########
  7. # 修改active启动内存
  8. $ vim /opt/activemq/bin/env
  9. ACTIVEMQ_OPTS_MEMORY="-Xms64M -Xmx1G" # 找到此行
  10. # 改为如下,建议Xms和Xmx值为一致,并且是系统内存的一半
  11. ACTIVEMQ_OPTS_MEMORY="-Xms2G -Xmx2G"
  12. # 修改配置文件
  13. $ vim /opt/activemq/conf/activemq.xml
  14. # 找到(40行左右)
  15. # 注意:每个activemq的BrokerName必须相同,否则不能加入集群。
  16. <broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.data}">
  17. # 改为
  18. <broker xmlns="http://activemq.apache.org/schema/core" brokerName="activemq-cluster" dataDirectory="${activemq.data}" schedulerSupport="true">
  19. # useJmx="true" :网上有些文档增加了此参数,其实没必要,useJmx默认为true。
  20. # 找到82行左右,如下:
  21. <persistenceAdapter>
  22. <kahaDB directory="${activemq.data}/kahadb"/>
  23. </persistenceAdapter>
  24. 改为:
  25. <persistenceAdapter>
  26. <!-- <kahaDB directory="${activemq.data}/kahadb"/> -->
  27. <replicatedLevelDB
  28. directory="${activemq.data}/leveldb"
  29. replicas="3"
  30. bind="tcp://0.0.0.0:62621"
  31. zkAddress="192.168.20.2:2181,192.168.20.3:2181,192.168.20.4:2181"
  32. hostname="192.168.20.2" zkPath="/activemq/leveldb-stores"/>
  33. # hostname建议写为你机器的IP
  34. </persistenceAdapter>
  35. # zkAddress:为你zookeeper集群所有节点地址。
  36. # hostname:自定义即可,但参与集群的hostname不可冲突,建议配置为本机IP。
  37. # zkPath:自定义zookeeper中的存储路径。
  38. # 找到(91行左右),以下是定义存储文件最大限制,一般可能需要更改storeUsage中的值
  39. # tempUsaage是调整非持久文件限制
  40. # memoryUsage是调整内存使用限制,默认是java虚拟机可用内存的70%
  41. <systemUsage>
  42. <systemUsage>
  43. <memoryUsage>
  44. <memoryUsage percentOfJvmHeap="70" />
  45. </memoryUsage>
  46. <storeUsage>
  47. <storeUsage limit="100 gb"/>
  48. </storeUsage>
  49. <tempUsage>
  50. <tempUsage limit="50 gb"/>
  51. </tempUsage>
  52. </systemUsage>
  53. </systemUsage>
  54. # 找到(大概118行左右)
  55. <transportConnectors>
  56. <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
  57. <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  58. # 从这里开始注释 <!--
  59. <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  60. <transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  61. <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  62. <transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  63. --> # 注释到这里结束
  64. </transportConnectors>
  65. # 修改WEB管理页面监听地址及端口
  66. $ vim /opt/activemq/conf/jetty.xml
  67. <bean id="jettyPort" class="org.apache.activemq.web.WebConsolePort" init-method="start">
  68. <!-- the default port number for the web console -->
  69. <property name="host" value="0.0.0.0"/> # 监听地址
  70. <property name="port" value="8161"/> # 监听端口
  71. </bean>
  72. $ vim /opt/activemq/conf/jetty-realm.properties # 修改管理台用户密码
  73. admin: 123.com, admin
  74. # 注意:用户名和密码的格式是 用户名:密码:角色名。
  75. # 将修改好的activemq目录发送至其他节点
  76. $ cd /opt/
  77. $ for i in `seq 3 4`;do rsync -az apache-activemq-5.16.0 192.168.20.$i:/opt/;done

配置amq2

  1. $ ln -sf /opt/apache-activemq-5.16.0 /opt/activemq
  2. $ vim /opt/activemq/conf/activemq.xml
  3. # 找到89行,修改如下
  4. <persistenceAdapter>
  5. <!-- <kahaDB directory="${activemq.data}/kahadb"/> -->
  6. <replicatedLevelDB
  7. directory="${activemq.data}/leveldb"
  8. replicas="3"
  9. bind="tcp://0.0.0.0:62621"
  10. zkAddress="192.168.20.2:2181,192.168.20.3:2181,192.168.20.4:2181"
  11. hostname="192.168.20.3" zkPath="/activemq/leveldb-stores"/>
  12. # hostname建议写为你机器的IP
  13. </persistenceAdapter>
  14. # 可以通过zookeeper连接选项中的 weight 选项,控制master的选举
  15. # 具体可以参考官方文档:http://activemq.apache.org/replicated-leveldb-store.html

配置amq3

  1. $ ln -sf /opt/apache-activemq-5.16.0 /opt/activemq
  2. $ vim /opt/activemq/conf/activemq.xml
  3. # 找到89行,修改如下
  4. <persistenceAdapter>
  5. <!-- <kahaDB directory="${activemq.data}/kahadb"/> -->
  6. <replicatedLevelDB
  7. directory="${activemq.data}/leveldb"
  8. replicas="3"
  9. bind="tcp://0.0.0.0:62621"
  10. zkAddress="192.168.20.2:2181,192.168.20.3:2181,192.168.20.4:2181"
  11. hostname="192.168.20.4" zkPath="/activemq/leveldb-stores"/>
  12. # hostname建议写为你机器的IP
  13. </persistenceAdapter>

启动各个amq节点

  1. $ /opt/activemq/bin/activemq start # 每台机器执行此指令,启动amq
  2. # 如果启动失败,请查看日志
  3. $ tailf -200 /opt/activemq/data/activemq.log

检查activemq运行情况

  1. $ /opt/activemq/bin/activemq status # 查看amq的运行状态,其中会输出其pid号
  2. $ ss -lnptu | grep 34358 # 一般master节点会监听如下端口(其中有一个是随机的)
  3. # 我grep过滤的是activema的pid号
  4. tcp LISTEN 0 50 [::]:38347 [::]:* users:(("java",pid=34358,fd=14))
  5. tcp LISTEN 0 128 [::]:61616 [::]:* users:(("java",pid=34358,fd=147))
  6. tcp LISTEN 0 100 [::]:62621 [::]:* users:(("java",pid=34358,fd=143))
  7. tcp LISTEN 0 50 [::]:8161 [::]:* users:(("java",pid=34358,fd=150))
  8. $ ss -lnptu | grep 34933 # salve节点只会监听一个随机端口
  9. tcp LISTEN 0 50 [::]:34003 [::]:* users:(("java",pid=34933,fd=14))

集群节点分析

查看zookeeper信息

运行zookeeper工具进行监控,随机连接至一台zookeeper,如下:

Activemq集群部署 - 图5

连接后下图可以看到ActiveMQ有3个节点,其中0000000000节点的elected值不为空且address路径也不为空,可以确定为是master,这里3台的文件路径为之前设置的zkPath:

Activemq集群部署 - 图6

查看web管理台信息

在三台amq机器中,我们只能访问当前master的web控制台,salve是不会监听web控制台的,当master宕机后,slave选举出的master将继续监听web控制台端口,如下(admin/123.com 为我们在amq配置文件中自定义的):

Activemq集群部署 - 图7

Activemq集群部署 - 图8

Activemq集群部署 - 图9

能看到如上信息,就可以将amq的连接信息给开发小伙伴使用了。