Master Slave 架构模式

这种模式是基于文件共享锁的高可用集群,个人理解其实是一种 Failover 模式,可以是一主一从,也可以是一主两从。

本文使用 Docker 搭建一个主从模式的 ActiveMQ 5.8.0 集群,一个主节点,两个从节点。

ActiveMQ 镜像的创建可以参考 构建ActiveMQ镜像并运行

version: "2.1"
services:
activemq-A:
image: cocowool/activemq:5.8.0
hostname: activemq-A
expose:
- "8161"
- "61613"
ports:
- "8161:8161"
- "61613:61613"
volumes:
- ~/Projects/sh-valley/docker-conf/activemq/activemq-5.8.0-A.xml:/usr/local/apache-activemq-5.8.0/conf/activemq.xml
- ~/Projects/sh-valley/docker-conf/activemq/kahadb:/usr/local/apache-activemq-5.8.0/data/kahadb
networks:
- default
activemq-B:
image: cocowool/activemq:5.8.0
hostname: activemq-B
expose:
- "8162"
- "61614"
ports:
- "8162:8161"
- "61614:61613"
volumes:
- ~/Projects/sh-valley/docker-conf/activemq/activemq-5.8.0-B.xml:/usr/local/apache-activemq-5.8.0/conf/activemq.xml
- ~/Projects/sh-valley/docker-conf/activemq/kahadb:/usr/local/apache-activemq-5.8.0/data/kahadb
networks:
- default

其实两个配置文件是一样的,关键是将 kahadb 的目录利用本地文件实现在两个容器见共享。验证过程记录。

$ docker-compose up
Attaching to activemq_activemq-B_1, activemq_activemq-A_1
activemq-B_1 | INFO: Using default configuration
activemq-B_1 | (you can configure options in one of these file: /etc/default/activemq /root/.activemqrc)
activemq-B_1 |
activemq-B_1 | INFO: Invoke the following command to create a configuration file
activemq-B_1 | /usr/local/apache-activemq-5.8.0/bin/activemq setup [ /etc/default/activemq | /root/.activemqrc ]
activemq-B_1 |
activemq-A_1 | INFO: Using default configuration
activemq-A_1 | (you can configure options in one of these file: /etc/default/activemq /root/.activemqrc)
activemq-A_1 |
activemq-A_1 | INFO: Invoke the following command to create a configuration file
activemq-B_1 | INFO: Using java '/usr/local/jdk1.8.0_144/bin/java'
activemq-A_1 | /usr/local/apache-activemq-5.8.0/bin/activemq setup [ /etc/default/activemq | /root/.activemqrc ]
activemq-A_1 |
activemq-B_1 | INFO: Starting in foreground, this is just for debugging purposes (stop process by pressing CTRL+C)
activemq-A_1 | INFO: Using java '/usr/local/jdk1.8.0_144/bin/java'
activemq-A_1 | INFO: Starting in foreground, this is just for debugging purposes (stop process by pressing CTRL+C)
activemq-B_1 | Java Runtime: Oracle Corporation 1.8.0_144 /usr/local/jdk1.8.0_144/jre
activemq-B_1 | Heap sizes: current=1005056k free=989327k max=1005056k
activemq-B_1 | JVM args: -Xms1G -Xmx1G -Djava.util.logging.config.file=logging.properties -Dcom.sun.management.jmxremote -Djava.io.tmpdir=/usr/local/apache-activemq-5.8.0/tmp -Dactivemq.classpath=/usr/local/apache-activemq-5.8.0/conf; -Dactivemq.home=/usr/local/apache-activemq-5.8.0 -Dactivemq.base=/usr/local/apache-activemq-5.8.0 -Dactivemq.conf=/usr/local/apache-activemq-5.8.0/conf -Dactivemq.data=/usr/local/apache-activemq-5.8.0/data
activemq-B_1 | Extensions classpath:
activemq-B_1 | [/usr/local/apache-activemq-5.8.0/lib,/usr/local/apache-activemq-5.8.0/lib/camel,/usr/local/apache-activemq-5.8.0/lib/optional,/usr/local/apache-activemq-5.8.0/lib/web,/usr/local/apache-activemq-5.8.0/lib/extra]
activemq-B_1 | ACTIVEMQ_HOME: /usr/local/apache-activemq-5.8.0
activemq-B_1 | ACTIVEMQ_BASE: /usr/local/apache-activemq-5.8.0
activemq-B_1 | ACTIVEMQ_CONF: /usr/local/apache-activemq-5.8.0/conf
activemq-B_1 | ACTIVEMQ_DATA: /usr/local/apache-activemq-5.8.0/data
activemq-A_1 | Java Runtime: Oracle Corporation 1.8.0_144 /usr/local/jdk1.8.0_144/jre
activemq-A_1 | Heap sizes: current=1005056k free=989327k max=1005056k
activemq-A_1 | JVM args: -Xms1G -Xmx1G -Djava.util.logging.config.file=logging.properties -Dcom.sun.management.jmxremote -Djava.io.tmpdir=/usr/local/apache-activemq-5.8.0/tmp -Dactivemq.classpath=/usr/local/apache-activemq-5.8.0/conf; -Dactivemq.home=/usr/local/apache-activemq-5.8.0 -Dactivemq.base=/usr/local/apache-activemq-5.8.0 -Dactivemq.conf=/usr/local/apache-activemq-5.8.0/conf -Dactivemq.data=/usr/local/apache-activemq-5.8.0/data
activemq-A_1 | Extensions classpath:
activemq-A_1 | [/usr/local/apache-activemq-5.8.0/lib,/usr/local/apache-activemq-5.8.0/lib/camel,/usr/local/apache-activemq-5.8.0/lib/optional,/usr/local/apache-activemq-5.8.0/lib/web,/usr/local/apache-activemq-5.8.0/lib/extra]
activemq-A_1 | ACTIVEMQ_HOME: /usr/local/apache-activemq-5.8.0
activemq-A_1 | ACTIVEMQ_BASE: /usr/local/apache-activemq-5.8.0
activemq-A_1 | ACTIVEMQ_CONF: /usr/local/apache-activemq-5.8.0/conf
activemq-A_1 | ACTIVEMQ_DATA: /usr/local/apache-activemq-5.8.0/data
activemq-B_1 | Loading message broker from: xbean:activemq.xml
activemq-A_1 | Loading message broker from: xbean:activemq.xml
activemq-B_1 | INFO | Refreshing org.apache.activemq.xbean.XBeanBrokerFactory$1@68c4039c: startup date [Wed Sep 07 13:16:20 UTC 2022]; root of context hierarchy
activemq-A_1 | INFO | Refreshing org.apache.activemq.xbean.XBeanBrokerFactory$1@68c4039c: startup date [Wed Sep 07 13:16:20 UTC 2022]; root of context hierarchy
activemq-B_1 | INFO | PListStore:[/usr/local/apache-activemq-5.8.0/data/localhost/tmp_storage] started
activemq-B_1 | INFO | Using Persistence Adapter: KahaDBPersistenceAdapter[/usr/local/apache-activemq-5.8.0/data/kahadb]
activemq-A_1 | INFO | PListStore:[/usr/local/apache-activemq-5.8.0/data/localhost/tmp_storage] started
activemq-A_1 | INFO | Using Persistence Adapter: KahaDBPersistenceAdapter[/usr/local/apache-activemq-5.8.0/data/kahadb]
activemq-A_1 | INFO | Database /usr/local/apache-activemq-5.8.0/data/kahadb/lock is locked... waiting 10 seconds for the database to be unlocked. Reason: java.io.IOException: File '/usr/local/apache-activemq-5.8.0/data/kahadb/lock' could not be locked.
activemq-B_1 | INFO | KahaDB is version 4
activemq-B_1 | INFO | Recovering from the journal ...
activemq-B_1 | INFO | Recovery replayed 1 operations from the journal in 0.022 seconds.
activemq-B_1 | INFO | Apache ActiveMQ 5.8.0 (localhost, ID:activemq-B-41795-1662556582026-0:1) is starting
activemq-B_1 | INFO | Listening for connections at: tcp://activemq-B:61616?maximumConnections=1000&wireformat.maxFrameSize=104857600
activemq-B_1 | INFO | Connector openwire Started
activemq-B_1 | INFO | Listening for connections at: amqp://activemq-B:5672?maximumConnections=1000&wireformat.maxFrameSize=104857600
activemq-B_1 | INFO | Connector amqp Started
activemq-B_1 | INFO | Listening for connections at: stomp://activemq-B:61612?transport.closeAsync=false
activemq-B_1 | INFO | Connector stomp Started
activemq-B_1 | INFO | Listening for connections at: stomp+nio://activemq-B:61613?transport.closeAsync=false
activemq-B_1 | INFO | Connector stomp+nio Started
activemq-B_1 | INFO | Apache ActiveMQ 5.8.0 (localhost, ID:activemq-B-41795-1662556582026-0:1) started
activemq-B_1 | INFO | For help or more information please see: http://activemq.apache.org
activemq-B_1 | ERROR | Temporary Store limit is 51200 mb, whilst the temporary data directory: /usr/local/apache-activemq-5.8.0/data/localhost/tmp_storage only has 42398 mb of usable space
activemq-B_1 | INFO | Web console type: embedded
activemq-B_1 | INFO | ActiveMQ WebConsole initialized.
activemq-B_1 | INFO | Initializing Spring FrameworkServlet 'dispatcher'
activemq-B_1 | INFO | jolokia-agent: No access restrictor found at classpath:/jolokia-access.xml, access to all MBeans is allowed
activemq-A_1 | INFO | Database /usr/local/apache-activemq-5.8.0/data/kahadb/lock is locked... waiting 10 seconds for the database to be unlocked. Reason: java.io.IOException: File '/usr/local/apache-activemq-5.8.0/data/kahadb/lock' could not be locked.

根据启动的顺序不同,A、B 都有可能抢到锁对外提供服务,未抢到锁的实例日志一直会报无法解锁的错误,同时不会对外提供 Web Console 服务。使用 Python 的连接例子,发现 stomp.py 有一个问题不能很好的支持 failover。

Networks of Brokers

这是一种负载均衡的架构,各个 Broker 通过互相连接并共享队列信息,实现集群的负载均衡,即只要消费者连接到 Broker 网络中任意一台,就可以消费所有的消息。

这种方案主要关注 ActiveMQ 配置中的两个参数

  • TransportConnector,传输连接器参数主要控制服务端和客户端之间的通信方式
  • NetworkConnector,网络连接器参数主要控制服务端和服务端之间的通信

本文构建了这样一种架构,Broker1 作为与生产者沟通的节点,负责接收消息以及传递消费者反馈给生产者的消息,Broker2、Broker3作为与消费者沟通的节点,支持与大量的消费者建立链接。这种架构适用于消费者数量非常多,通常是超过1万个节点的情况。根据实际生产运行的情况,一台4C16G的虚拟机,一个ActiveMQ实例通常能够承受2000个左右的链接能保持长期稳定运行。

具体的 docker 配置如下,相关的文件可以从我的 Github 上下载。

version: "2.1"
services:
activemq-broker1:
image: cocowool/activemq:5.8.0
hostname: activemq-broker1
expose:
- "8161"
- "61611"
ports:
- "8161:8161"
- "61611:61612"
volumes:
- ~/Projects/sh-valley/docker-conf/activemq-network/activemq-5.8.0-broker1.xml:/usr/local/apache-activemq-5.8.0/conf/activemq.xml
networks:
activemq-network:
ipv4_address: 172.28.1.11
activemq-broker2:
image: cocowool/activemq:5.8.0
hostname: activemq-broker2
expose:
- "8162"
- "61612"
ports:
- "8162:8161"
- "61612:61612"
volumes:
- ~/Projects/sh-valley/docker-conf/activemq-network/activemq-5.8.0-broker2.xml:/usr/local/apache-activemq-5.8.0/conf/activemq.xml
networks:
activemq-network:
ipv4_address: 172.28.1.12
activemq-broker3:
image: cocowool/activemq:5.8.0
hostname: activemq-broker3
expose:
- "8163"
- "61613"
ports:
- "8163:8161"
- "61613:61612"
volumes:
- ~/Projects/sh-valley/docker-conf/activemq-network/activemq-5.8.0-broker3.xml:/usr/local/apache-activemq-5.8.0/conf/activemq.xml
networks:
activemq-network:
ipv4_address: 172.28.1.13
networks:
activemq-network:
ipam:
config:
- subnet: 172.28.1.0/24

执行 docker-compose up 命令可以启动三个 ActiveMQ 实例,然后分别通过 http://localhost:8161\8162\8163 可以查看三个实例的控制台,在 Broker2\Broker3 的 Network 页签下可以看到到 Broker1 的链接。我们在生产实践过程中发现过这个连接出问题的情况,此时 ActiveMQ 实例进程并无异常,这时就会影响连接到这个实例的消费者。

要测试这种架构的可用性,可以参考 Python 与 ActiveMQ 交互的一些例子 中的代码示例,修改对应的端口地址就能看到效果。

这个架构可以配合 Master Slave 进一步优化,如下图所示:

生产者连接的实例采用 Master Slave Failover 方式,消费者连接的实例在配置 NetworkConnector 时也采用 Failover 模式,这样 Broker1 就提供了主从的高可用模式,进一步提高了整个集群应对风险的能力。

参考资料

  1. ActiveMQ集群安装
  2. Persistence vs. Durability in Messaging. Do you know the difference?
  3. Shared File System Master Slave
  4. Networks of Brokers
  5. docker-compose 固定IP
  6. ActiveMQ实现负载均衡+高可用部署方案
  7. ActiveMQ中的NetworkConnector(网络连接器)详解

ActiveMQ 常见集群模式的更多相关文章

  1. Azure上搭建ActiveMQ集群-基于ZooKeeper配置ActiveMQ高可用性集群

    ActiveMQ从5.9.0版本开始,集群实现方式取消了传统的Master-Slave方式,增加了基于ZooKeeper+LevelDB的实现方式. 本文主要介绍了在Windows环境下配置基于Zoo ...

  2. Redis 5.0.7 讲解,单机、集群模式搭建

    Redis 5.0.7 讲解,单机.集群模式搭建 一.Redis 介绍 不管你是从事 Python.Java.Go.PHP.Ruby等等... Redis都应该是一个比较熟悉的中间件.而大部分经常写业 ...

  3. ActiveMQ的集群方案对比及部署

    转载:http://blog.csdn.net/lifetragedy/article/details/51869032 ActiveMQ的集群 内嵌代理所引发的问题: 消息过载 管理混乱 如何解决这 ...

  4. 深入剖析Redis系列: Redis集群模式搭建与原理详解

    前言 在 Redis 3.0 之前,使用 哨兵(sentinel)机制来监控各个节点之间的状态.Redis Cluster 是 Redis 的 分布式解决方案,在 3.0 版本正式推出,有效地解决了 ...

  5. ActiveMQ伪集群部署

    本文借鉴http://www.cnblogs.com/guozhen/p/5984915.html,在此基础上进行了完善,使之成为一个完整版的伪分布式部署说明,在此记录一下! 一.本文目的 介绍如何在 ...

  6. ActiveMQ实战-集群

    原文:http://blog.csdn.net/lifetragedy/article/details/51869032 ActiveMQ的集群 内嵌代理所引发的问题: 消息过载 管理混乱 如何解决这 ...

  7. activemq 搭建--集群

      linux activmemq 集群安装,配置和高可用测试       从 ActiveMQ 5.9 开始,ActiveMQ 的集群实现方式取消了传统的Master-Slave 方式,增加了基于Z ...

  8. Redis 单机模式,主从模式,哨兵模式(sentinel),集群模式(cluster),第三方模式优缺点分析

    Redis 的几种常见使用方式包括: 单机模式 主从模式 哨兵模式(sentinel) 集群模式(cluster) 第三方模式 单机模式 Redis 单副本,采用单个 Redis 节点部署架构,没有备 ...

  9. master挂了的话pm2怎么处理 使用pm2方便开启node集群模式

    本文为转载 Introduction As you would probably know, Node.js is a platform built on Chrome's JavaScript ru ...

  10. 数据源管理 | 搜索引擎框架,ElasticSearch集群模式

    本文源码:GitHub·点这里 || GitEE·点这里 一.集群环境搭建 1.环境概览 ES版本6.3.2,集群名称esmaster,虚拟机centos7. 服务群 角色划分 说明 en-maste ...

随机推荐

  1. goroutine调度

    0.1.索引 https://blog.waterflow.link/articles/1662974432717 1.进程 一个进程包含可以由任何进程分配的公共资源.这些资源包括但不限于内存地址空间 ...

  2. 「MySQL高级篇」explain分析SQL,索引失效&&常见优化场景

    大家好,我是melo,一名大三后台练习生 专栏回顾 索引的原理&&设计原则 欢迎关注本专栏:MySQL高级篇 本篇速览 在我们上一篇文章中,讲到了索引的原理&&设计原则 ...

  3. 一、docker的介绍

    一.虚拟化和容器 虚拟化介绍 操作系统层虚拟化是指通过划分一个宿主操作系统的特定部分,产生一个个隔离的操作执行环境.操作系统层的虚拟化是操作系统内核直接提供的虚拟化,虚拟出的操作系统之间共享底层宿主操 ...

  4. Archlinux + Dwm 配置流程

    本着学习C的态度来了解dwm,本身作为一个i3wm的追崇者,与dwm会擦出怎么样的火花呢? 下载安装dwm archlinuxcn源配置 编辑/etc/pacman.conf文件,添加bfsu的arc ...

  5. BigDecimal精度详解

    [BigDecimal精确度的计数保留法及精度丢失的解决办法] 目录 BigDecimal精确度的计数保留法 1.ROUND_UP 2.ROUND_DOWN 3.ROUND_HALF_UP 4.ROU ...

  6. 系统启动后bond配置不生效问题定位

    背景描述 为了适配新功能,裸金属服务的磁盘镜像中做了如下修改: dracut添加network, iscsi模块 grub添加rd.iscsi.firmware=1参数 删除网卡配置文件/etc/sy ...

  7. Java:ArrayList的基本使用(学习笔记)

    ​ 集合和数组的对比(为什么要有集合) 分为俩点 1. 长度:数组的长度是固定的,集合的长度是可变的. 2. 存储类型: 数组:可以存储基本数据类型,引用数据类型. 集合:只能存储引用数据类型. 小t ...

  8. .NET MAUI 安卓应用开发初体验

    一..NET MAUI开发环境搭建&安卓SDK和安卓模拟器安装提示网络连接失败问题解决 引言 本节目标是帮助第一次搭建.NET MAUI开发环境,在下载安卓SDK和安卓模拟器过程中一直提示网络 ...

  9. C# DataTable 虚拟Sql临时表,可以做一些处理

    /// <summary> /// 获取临时表-和数据库表一样的的表结构的才可以 /// </summary> /// <param name="SourceT ...

  10. JS基础笔记合集(1-3)

    JavaScript合集 1. JS入门基础 2. JS数据类型 3. JS运算符 4. JS流程控制 5. JS对象 6. JS函数 7. JS面向对象 8. JS数组 9. JS内置对象 我追求理 ...