ActiveMQ集群(一) —— Master-Slave
ActiveMQ的集群方式主要由两种:Master-Slave和Broker Cluster。
Master-Slave方式中,只能是Master提供服务,Slave是实时地备份Master的数据,以保证消息的可靠性。 当Master失效时,Slave会自动升级为Master,客户端会自动连接到Slave上工作。
Master-Slave模式分为四类:
- Pure Master Slave
- Shared File System Master Slave
- JDBC Master Slave
- Replicated LevelDB Store
注意: Master-Slave方式都不支持负载均衡,但可以解决单点故障的问题,以保证消息服务的可靠性。
Pure Master Slave
ActiveMQ5.8以前支持,自从Activemq5.8开始,Activemq的集群实现方式取消了传统的Pure Master Slave方式,并从Activemq5.9增加了基于zookeeper+leveldb的实现方式。
使用两个ActiveMQ服务器,一个作为Master,Master不需要做特殊的配置;另一个作为Slave,配置activemq.xml
文件,在<broker>节点中添加连接到Master的URI和设置Master失效后不关闭Slave。
看到之前的ActiveMQ应该知道,这里我们演示使用的ActiveMQ版本为5.15.7(并且这都不是最新的),这里我们就不演示该集群方式的,感兴趣的同学可以自己尝试一下,其主要步骤就是上述说的,只需要Slave端的ActiveMQ的配置文件中进行配置忌口,可参考官网文档http://activemq.apache.org/pure-master-slave.html
Shared File System Master Slave
利用共享文件系统做ActiveMQ集群,是基于ActiveMQ的默认数据库kahaDB完成的,kahaDB的底层是文件系统。这种方式的集群,Slave的个数没有限制,哪个ActiveMQ实例先获取共享文件的锁,那个实例就是Master,其它的ActiveMQ实例就是Slave,当当前的Master失效,其它的Slave就会去竞争共享文件锁,谁竞争到了谁就是Master。这种模式的好处就是当Master失效时不用手动去配置,只要有足够多的Slave。
但是该模式也存在一个缺点,就是我们不能够把所有的ActiveMQ集群部署在同一台机器上呀,一般的话可能会在存在不同的机器上,那么就需要用到分布式文件系统了。
Shared JDBC Master Slave
JDBC Master Slave模式和Shared File Sysytem Master Slave模式的原理是一样的,其中唯一不同的是,只是把共享文件系统换成了共享数据库。我们只需在所有的ActiveMQ的主配置文件中activemq.xm
l添加数据源,所有的数据源都指向同一个数据库,然后修改持久化适配器。
这种方式的集群相对Shared File System Master Slave更加简单,更加容易地进行分布式部署,当然肯定也有是缺点的,如数据库假如失效的话,那么所有的ActiveMQ实例都将失效。
这里我们就来测试一下,首先我们在本地准备三个ActiveMQ,然后因为在本地进行集群测试,所以我们需要修改其 conf 目录下配置文件activemq.xml
和jetty.xml
中的端口号,主要是61616服务端口,以及8161控制台页面端口
上述我们分别改为61616、61617、61618 和 8161、8162、8163 端口。
然后我们还需要为每个ActiveMQ开启网络监控功能useJmx="true"
,如下:
最后就需要就为将每个ActiveMQ默认的存储机制有KahaDB改为数据库存储即可,这个我们在ActiveMQ存储的持久化机制以及介绍过了,如下:
这样就配置完成了,我们就可以依次启动三个ActiveMQ服务了,服务启动后,如下:
可以看到只有一台MQ成为Master,其余两台成为Slave并会尝试成为Master,并不断重试。且两台Slave的管理控制台将无法访问。
然后我们在代码中几乎不用做太大的修改,只需修改其ActiveMQ的连接地址即可
在默认情况下,failover机制从URI列表中随机选择出一个URI进行连接,这可以有效地控制客户端在多个broker上的负载均衡,但是要使客户端首先连接到主节点,并在主节点不可用时只连接到辅助备份代理,需要设置randomize = false
。
然后我们就可以启动生产者和消费者了进行正常的通信了,当我们关闭一台ActiveMQ服务,剩余两台时,服务依旧可用,在关闭一台,剩余一台ActiveMQ服务时,也是可以进行正常的通信的。
Replicated LevelDB Store
ActiveMQ5.9以后才新增的特性,使用ZooKeeper协调选择一个node作为master。被选择的master broker node开启并接受客户端连接。 其他node转入slave模式,连接master并同步他们的存储状态。slave不接受客户端连接。所有的存储操作都将被复制到连接至Master的slaves。
如果master死了,得到了最新更新的slave被允许成为master。推荐运行至少3个replica nodes。
如上图还必须要依赖于Zookeeper,用来以协调选择一个服务作为master,那么为什么在Shared JDBC Master Slave中就不需要依赖于Zookeeper呢?原因在ActiveMQ存储的持久化机制已经提过到了,在ActiveMQ使用数据库作为持久化机制时,在数据库中会创建三种表,其中ACTIVEMQ_LOCK表就是用来确定集群的Master Broker
这里我们Replicated LevelDB Store采用的是ActiveMQ内置的LevelDB,LevelDB是一个Google实现的非常高效的kv数据库,目前的版本1.2能够支持billion级别的数据量了。 在这个数量级别下还有着非常高的性能,采用单进程的服务,性能非常之高,在一台4核Q6600的CPU机器上,每秒钟写数据超过40w,而随机读的性能每秒钟超过10w。
由此可以看出,具有很高的随机写,顺序读/写性能,但是随机读的性能很一般,也就是说,LevelDB很适合应用在查询较少,而写很多的场景。LevelDB应用了LSM (Log Structured Merge) 策略,通过一种类似于归并排序的方式高效地将更新迁移到磁盘,降低索引插入开销。
从上述的描述看到LevelDB就非常适合ActiveMQ,因为其写入性能好就可以了,一般情况下ActiveMQ很少会进行读取数据,其存储的目的是持久化,一般都在内存中完成了,消息消费后会进行删除,删除也是一种写入的行为,只有很少的情况下,服务进行重启,才会进行读取。
然后我们就来看看如何配置,其配置非常简单,首先我们还是和上述一样,在本地启动三个ActiveMQ服务,并修改其端口号(上述已介绍),然后我们还需配置每个ActiveMQ的配置文件activemq.xml
,几乎都差不多,如下:
配置项说明:
- directory: 持久化数据存放地址
- replicas: 集群中节点的个数
- bind: 集群通信端口
- zkAddress: ZooKeeper集群地址
- hostname: 当前服务器的IP地址,如果集群启动的时候报未知主机名错误,那么就需要配置主机名到IP地址的映射关系。
- zkPath: ZooKeeper数据挂载点
然后我们先启动Zookeeper服务,然后再依次启动三个ActiveMQ服务,这里只有当服务数过半集群才能正常的运行,如下:
然后我们在启动61617,集群过半可以正常运行,发现61617被选举为Master节点
最后我们在启动61618,肯定也是一个Slave节点,因为Master已经被选举出来了,这里我们我们在启动消息的生产者和消费者进行测试,代码和之前一致,和上述一样修改下连接地址即可,测试发现消息收发正常。
这里我们将上述的61617 master服务关闭,发现61616被选举为master,然后再进行测试,发现集群也是可以正常运行的。