最近刚开始玩Docker和ActiveMQ刚好学习到ActiveMQ集群的搭建,就将其记录了下来给有需要的人,也可以跟大家交流交流。

    这里先感谢慕课网和http://blog.csdn.net/lifetragedy/article/details/51869032,在学习ActiveMQ有很大的帮助。

    一、docker坏境的搭建。

    这里重点不是docker,而是基于docker搭建的ActiveMQ集群,docker了解的也可以参考http://www.docker.org.cn/
    
  •     Ubuntu安装docker

Docker 要求 Ubuntu 系统的内核版本高于 3.10,可以通过uname -r来查看。

wget -qO- https://get.docker.com/ | sh

当要以非root用户可以直接运行docker时,需要执行 sudo usermod -aG docker runoob 命令,然后重新登陆,否则会报错,安装完成之后可以通过docker version来查看状态。

也可以通过curl来进行安装,which curl 命令是否安装curl,没有安装则通过 sudo apt-get update 和 sudo apt-get install curl 进行安装。

curl -sSL https://get.docker.com/ | sh 

这种安装方式的好处是安装的版本是最新的,或者也可以使用sudo apt-get install docker这种安装方式比较方便,但版本不是最新的,基于你的软件源。

  • Linux系统
yum -y install docker

经典的安装方式,方便快捷。

  • Mac系统

没什么好说的,https://www.oschina.net/translate/installing-docker-on-mac-os-x

  • Windows系统

Docker 引擎是基于Linux 内核,所以我们需要在 Windows 上安装Boot2Docker 来安装虚拟机和运行 Docker。

最新版 Boot2Docker 下载地址: https://github.com/boot2docker/windows-installer/releases/latest

目前最新版为v1.8.0, 下载地址为: https://github.com/boot2docker/windows-installer/releases/download/v1.8.0/docker-install.exe

    二、在docker中搭建activemq

首先我先从dockerhub上拉取ActiveMQ镜像,不过我网络比较慢,所以我从阿里拉取的镜像。

#这是阿里云镜像仓库的地址
docker pull registry.cn-hangzhou.aliyuncs.com/daydayup/activemq

#这是dockerhub
docker pull webcenter/activemq

 

 拉取完镜像之后我们可以通过docker images来查看镜像,然后使用docker run 命令来运行(可以结合自身给出不同的命令),这里出于演示目的使用了自动分配端口映射。

 

这样我们的容器就运行起来了,下一步我们要做什么呢?该实例来源慕课网的 jovezhao 老师

到这里我们要来开始分析我们的工作了,我们要建立的集群是一个三个节点的集群,分别是一个master节点和一个slave以及一个中间cluster节点。

 

 图中所表示的Node A即 cluster 节点,不进行消息的持久化,即将生产者的消息同步过来,然后发送给消费者消费。

而Node B即表示 master 节点,进行消息的生产并持久化到文件系统中,并将消息同步到 Node A(Cluster)节点。

而Node C即表示 slave 节点,属于备用节点,等待 master 释放锁,当 master 释放锁后取代Node B 称为 master节点。

 

 

这里需要注意的是master节点跟slave节点都共用一个文件系统,并且跟cluster节点可以相互通信。

 而我们的集群是基于docker来搭建的,so?问题出来了,我们知道每个ActiveMQ在docker眼里就是一个运行着的容器,那么容器的文件系统跟节点访问都需要修改其配置文件,

可是配置文件在容器内部,这个问题有几个解决方案(我所知的):

1.docker commit 该命令相当于在容器上追加一层(docker每个容器都是以层来区分的)

2.dockerfile 定制镜像,就是在原有基础镜像上添加一条条指令,相当于给每一层进行配置

3.docker cp 命令修改(覆盖)容器中的配置文件(不推荐)

4.启动时进行文件映射,这也是我使用的方法,比较简单,更好的方法是使用定制镜像,不过出于测试目的也可以更加了解其内容。

我们先使用 docker cp 从容器内部复制配置文件到本地文件系统(官方给出的配置文件地址是在/opt/activemq/conf/activemq.xml)。

 我们可以通过 docker exec -it 容器id /bin/bash 进入运行着的容器中(每个容器可以抽象的理解成一台虚拟机)。

而后找到我们所需要的配置文件,退出容器,通过 docker cp 命令将容器文件拷贝到本地系统中。、

docker cp 容器名:要拷贝的文件在容器里面的路径 要拷贝到宿主机的相应路径

root@ubuntu:/home/yang# docker cp 2263:/opt/apache-activemq-5.13.3/conf/activemq.xml /myConfig/activemq/activemq-master-a.xml
root@ubuntu:/myConfig/activemq# cd /myConfig/activemq/
root@ubuntu:/myConfig/activemq# ls
activemq-clusters-a.xml  activemq-master-c.xml  activemq-slave-c.xml
activemq-master-a.xml    activemq-slave-a.xml
activemq-master-b.xml    activemq-slave-b.xml

 

 这里我复制了比较多份用于我以后的测试开发。

首先我们先来修改 Cluster 节点的配置文件,相对比较简单。

      <!-- 这里是默认的端口配置,我们都需要,只留下一个61616端口即可,由于是测试所以节点机只要端口不一致即可 -->
     <transportConnectors>
            <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
            <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
           <!-- <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/> -->
        </transportConnectors>

      <!-- 配置网络代理,cluster 节点需要与 master 跟 slave 进行穿透 -->
        <networkConnectors>
                <networkConnector uri="static:(tcp://192.168.1.106:61617,tcp://192.168.1.106:61618)" duplex="true" />
        </networkConnectors>

 

 

连接到网络代理的两种方式:

  • 静态的方法配置访问特定的网络代理 Static:(uri1,uri2,uri3,…)?key=value 或是Failover:(uri1, … , uriN)?key=value
  • 发现中介(agents)动态的探测代理
duplex参数用来消息同步,即 master 节点生产出消息,会变成一个 sender 把消息 cluster,同理,cluster 接收到消息也会发送给 master,称为互相穿透。

下面是 master 节点的配置文件
        <transportConnectors>
            <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
           <transportConnector name="openwire" uri="tcp://0.0.0.0:61617?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600" />
           <!-- <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/> -->
        </transportConnectors>

        <networkConnectors>
                <networkConnector uri="static:(tcp:192.168.1.106:61616)" duplex="true" />
        </networkConnectors>

 

下面是 slave 节点的配置文件

            <transportConnector name="openwire" uri="tcp://0.0.0.0:61618?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <!-- <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/> -->
        </transportConnectors>

        <networkConnectors>
                <networkConnector uri="static:(tcp://192.168.1.106:61616)" duplex="true" />
        </networkConnectors>

 

 

这样我们的节点连接就配置好了,其实这里还有一个重要的步骤被我们忽略掉了,或者说是略过。

这个步骤就是公用文件系统,在配置文件中有这样一项配置

     <persistenceAdapter>
            <kahaDB directory="${activemq.data}/kahadb"/>
        </persistenceAdapter>

 

 用来指定持久化文件地址,而由于我们这里使用的是docker来运行容器,并使用文件映射的方式来指定,所以这一步骤我们可以忽略,不过cluster中需要将这项配置进行注释,

因为cluster是不作为生产者来使用的,当然如果我们生产消息时不调用该节点,这项配置也是可以省略的(理论上来说可行)。

然后我们需要要在本地文件中创建一个目录用来进行持久化(正确的做法是使用网络文件系统,我正在学习),这一步我就省略了。

接着就是启动我们的容器,slave节点是要晚于master节点的,其次两个顺序无关紧要。

root@ubuntu:~# docker run -it -d -p 61617:61616 -p 8171:8161 -v /myConfig/activemq/activemq-master-a.xml:/opt/apache-activemq-5.13.3/conf/activemq.xml -v /usr/share/activemq/kahadb:/opt/apache-activemq-5.13.3/data/kahadb registry.aliyuncs.com/daydayup/activemq
054cf0a41e5dbd08fbb268e5023f705d618f95cb679c6c665e7e8bea3b195559
root@ubuntu:~# docker run -it -d -p 61616:61616 -p 8161:8161 -v /myConfig/activemq/activemq-clusters-a.xml:/opt/apache-activemq-5.13.3/conf/activemq.xml registry.aliyuncs.com/daydayup/activemqca9534226020534e258f4ffb34c0eb0f9a97740a5ee72e390d350d2ceb0eee0d
root@ubuntu:~# docker run -it -d -p 61618:61616 -p 8181:8161 -v /myConfig/activemq/activemq-slave-a.xml:/opt/apache-activemq-5.13.3/conf/activemq.xml -v /usr/share/activemq/kahadb:/opt/apache-activemq-5.13.3/data/kahadb registry.aliyuncs.com/daydayup/activemq
327f1daba83fd56c40abac31b41f7f4435f3ee7b40e4b1719a69000248a39f0f
root@ubuntu:~# docker ps
CONTAINER ID        IMAGE                                     COMMAND                  CREATED              STATUS              PORTS                                              NAMES
327f1daba83f        registry.aliyuncs.com/daydayup/activemq   "/bin/sh -c '/opt/apa"   8 seconds ago        Up 4 seconds        0.0.0.0:8181->8161/tcp, 0.0.0.0:61618->61616/tcp   nostalgic_ride
ca9534226020        registry.aliyuncs.com/daydayup/activemq   "/bin/sh -c '/opt/apa"   About a minute ago   Up 58 seconds       0.0.0.0:8161->8161/tcp, 0.0.0.0:61616->61616/tcp   reverent_euler
054cf0a41e5d        registry.aliyuncs.com/daydayup/activemq   "/bin/sh -c '/opt/apa"   About a minute ago   Up About a minute   0.0.0.0:8171->8161/tcp, 0.0.0.0:61617->61616/tcp   tender_yalow

 

 此时我们可以先通过查看端口来验证容器是否启动成功

root@ubuntu:/usr/share/activemq/kahadb# netstat -an | grep 61616
tcp6       0      0 :::61616                :::*                    LISTEN     
root@ubuntu:/usr/share/activemq/kahadb# netstat -an | grep 61617
tcp6       0      0 :::61617                :::*                    LISTEN     
root@ubuntu:/usr/share/activemq/kahadb# netstat -an | grep 61618
tcp6       0      0 :::61618                :::*                    LISTEN 

 

可以看到三个端口都对外开放了,我们在使用浏览器访问管理器试试效果

 

可以看到slave节点已经被阻塞了,而master节点跟cluster节点都可以正常使用。

我们的集群这就搭建完成了,不过进一步的验证需要代码进行验证,还有文件系统的验证我就不一一演示了。

当我们需要更加复杂的集群都可以通过这种方式进行搭建,并在此基础上进行升级。

好了,基于docker搭建的activemq到这里就结束了,大家有什么问题可以找我交流,我也是刚接触可能有些地方误解,请及时指出,谢谢你的耐心观看。