Docker swarm结合Openresty部署rabbitmq集群

  大家好,年底了,年味儿越来越浓了.2019年的寒冬被定义为未来10年中最好的一年,对于这一说法悲观的人和乐观的人的理解是不一样的.但是不管是寒冬还是盛夏,我们都应该坚持不断的积累和主动的思考.拥抱变化,坚定信心.

  

简单描述一下我们的需求,就是通过docker 来搭建一套rabbitmq的集群,用于接受业务传来的数据,然后把数据写到消息队列中,然后消费者消费消息,生成日志文件,接着大数据采集系统定时来采集数据.这样做的一个好处就是,我们的服务可以直接部署到业务系统所在的服务器集群中.     

  年末的时候,在忙完了各种活动项目之后,接到了一个新的项目,数据打点项目.需要在各指定机房搭建数据采集服务,然后有数据中心定时去拉取数据.为此我们采用的解决方案是 基于docker 搭建rabbitmq,利用Openresty 来进行数据的生产和nginx代理.来,让我们一起了解一些概念.

以下内容是从官网搬来的:

  OpenResty® 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

  OpenResty® 通过汇聚各种设计精良的 Nginx 模块(主要由 OpenResty 团队自主开发),从而将 Nginx 有效地变成一个强大的通用 Web 应用平台。这样,Web 开发人员和系统工程师可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,快速构造出足以胜任 10K 乃至 1000K 以上单机并发连接的高性能 Web 应用系统。

  OpenResty® 的目标是让你的Web服务直接跑在 Nginx 服务内部,充分利用 Nginx 的非阻塞 I/O 模型,不仅仅对 HTTP 客户端请求,甚至于对远程后端诸如 MySQL、PostgreSQL、Memcached 以及 Redis 等都进行一致的高性能响应。

  之所以选择OpenResty,是看中了其中nginx服务和对lua脚本的支持,nginx可以做服务代理,lua脚本我们可以用来编写消息生产者的脚本.好了,开始我们的部署之旅吧(再罗嗦一句,你需要提前了解docker,同时保证部署环境已经安装了docker,为了部署成功,请保证有俩台服务器,或者虚拟机也行,同时保持俩台服务器或者虚拟机的ip在统一网段)!

  

  一.搭建swarm集群

  swarm集群的角色包含有leader,node 在swarm集群搭建中,重要的是保证 token的一致

1.swarm manager(初始化swarm leader): docker swarm init --advertise-addr 192.168.7.201

提示:这一步会产生token,token为swarm集群的唯一标识

    2.swarm group(成员加入集群)

    docker swarm join --token SWMTKN-1-35ucts3e9bg5onl1pyqwh03j1z1micdb88ziq78m4pfr1zulhf-70w2bdzpjyr8xqc1p77mue04r  192.168.7.201:2377

token是在初始化swarm manager时返回的.

    注意:记得为集群成员追加label,便于rabbitmq绑定相应的节点,bi-tool-02是节点名称

    docker node update --label-add rabbitmq=master bi-tool-02

    docker node update --label-add rabbitmq=slave1 bi-tool-01

这里的label是我们给swarm集群中各节点起的一个别名,以 docker node update --label-add rabbitmq=master bi-tool-02 为例,是给节点bi-tool-02增加标签,标签为: rabbitmq=master  ,我们可以通过 docker node inspect bi-tool-02 来查看节点配置内容.可以看到的内容如下:

   "Labels": {

      "rabbitmq": "master"

   },

  追加标签的目的是为了我们在搭建rabbitmq集群的时候,方便rabbitmq节点的绑定.

  二.启动network服务

  network 用于提供容器间通许

命令:docker network create --driver overlay rabbitmq-network

  三.搭建rabbitmq集群

        1.创建镜像

   docker build -t stomp-rabbitmq:latest .  

创建镜像所需要的dockerfile文件见附件 (博客园不能上传附件吗????等我咨询完了,我再补充这个附件)

放在了百度网盘上:

   https://pan.baidu.com/s/1PI1nL6TL9pJxsWUaTBleig

提取码:sg9p

2.创建rabbitmq master队列

   命令(master):sudo docker service create --name stomp-rabbitmq-master --hostname="stomp-rabbitmq-master" --network rabbitmq-network -p 5772:5672 -p 15772:15672 -p 12345:12345 --mount type=bind,target=/var/lib/rabbitmq/,source=/home/agent/rabmq/ --constraint node.labels.rabbitmq==master -e RABBITMQ_CLUSTER_NODES='rabbit@stomp-rabbitmq-slave1' -e "AUTOCLUSTER_CLEANUP=true" -e "CLEANUP_WARN_ONLY=false" -e "RABBITMQ_ERLANG_COOKIE=thisissecretkey"  stomp-rabbitmq:latest

  注意:要确保/home/agent/rabmq/ 路径的存在

  备注:

  --network 为设置网络环境,rabbitmq-network是创建好的docker network,类型为overlay。

  -p 为将容器的端口暴露到宿主机的端口上,这样可以通过宿主机也就是服务器的端口访问到容器对应的端口,前方前为宿主机端口,后方为容器端口。其中5672为amqp通信端口,15672为管理界面端口,12345为stomp通信端口。

  --mount 为将容器内的目录映射到宿主机上(/var/lib/rabbitmq/ 保存了队列与交换机等的信息,而且保存了持久化的队列里的消息),这样当容器出现问题时,启动新容器时由于已经挂载到了宿主机上持久化,关键信息可以不丢失,新容器相当于和旧容器一样。前方为容器,后方为宿主机目录。

  --constraint 为创建service时将service指定在某台机器上创建,本次使用的是通过lable指定,在之前我已经对这三台服务器进行了label指定。

  -e 为指定容器内的环境变量,比如其中的    "RABBITMQ_ERLANG_COOKIE=thisissecretkey"

3.创建rabbitmq slave 队列

  命令(slave):sudo docker service create --name stomp-rabbitmq-slave1 --hostname="stomp-rabbitmq-slave1" --network rabbitmq-network -p 5773:5672 -p 15773:15672 -p 23456:12345 --mount type=bind,target=/var/lib/rabbitmq/,source=/home/agent/rabmq/ --constraint node.labels.rabbitmq==slave1 -e RABBITMQ_CLUSTER_NODES='rabbit@rabbitmq-master' -e "AUTOCLUSTER_CLEANUP=true" -e "CLEANUP_WARN_ONLY=false" -e "RABBITMQ_ERLANG_COOKIE=thisissecretkey" stomp-rabbitmq:latest

在执行完 sudo docker service create --name stomp-rabbitmq-slave1 后,其实就相当于启动了一个容器,可以通过 docker ps 看到,如果看不到,那说明服务启动失败,通过进程守护进入容器用到的 id 就是 此处看到的id

  (将分支1加入到集群),通过守护进程进入到容器内部执行

(进入容器)命令:docker exec -it 36383eefcf87 /bin/sh

docker exec -it  /bin/sh

   rabbitmqctl stop_app
   rabbitmqctl join_cluster rabbit@stomp-rabbitmq-master
   rabbitmqctl start_app

 4.创建Openresty(nginx+lua)

   docker build -t openresty-product:0.0.1 .

        命令:docker service create  --name openresty-product-service --mode global -p 8080:80 --mount type=bind,target=/var/log/nginx/,source=/home/agent/openresty-file/var/log/nginx --mount type=bind,target=/opt/,source=/home/agent/openresty-file/openrestyFile --mount type=bind,target=/etc/nginx/conf.d,source=/home/agent/openresty-file/etc/nginx/conf.d --mount type=bind,target=/usr/local/openresty/nginx/conf,source=/home/agent/openresty-file/usr/local/openresty/nginx/conf openresty-product:0.0.1

        用于外网访问下载数据文件

        命令:docker service create  --name openresty-file-server --constraint node.labels.rabbitmq==master -p 80:80 --mount type=bind,target=/var/log/nginx/,source=/home/agent/finalDataFile/var/log/nginx --mount type=bind,target=/opt/,source=/home/agent/finalDataFile --mount type=bind,target=/etc/nginx/conf.d,source=/home/agent/finalDataFile/etc/nginx/conf.d openresty/openresty:xenial

nginx 的相关配置,我们就不在此细说了,我可以给大家看个例子

server {
listen ;
server_name localhost; #charset koi8-r;
access_log /var/log/nginx/host.access.log main; location / {
root /usr/local/openresty/nginx/html;
index index.html index.htm;
} location /hello {
# root /usr/local/openresty/nginx/html;
# index index.html index.htm; default_type 'text/html';
content_by_lua 'ngx.say("hello world")';
} location /file {
proxy_pass http://192.168.7.201:8090/;
access_log /var/log/nginx/file.access.log main;
error_log /var/log/nginx/file.error.log;
} location /dataagent/v1/test {
# deny all;
default_type 'text/html';
# lua_code_cache off;
# content_by_lua 'ngx.say("test.test.com access")';
access_log /var/log/nginx/chaoshen.access.log main;
error_log /var/log/nginx/chaoshen.error.log;
content_by_lua_file /opt/openresty-docker/openresty/lua-dataagent/chaoshen_yuenan.lua;
} error_page /50x.html;
location = /50x.html {
root /usr/local/openresty/nginx/html;
} }
配置中 /dataagent/v1/test content_by_lua_file 对应的脚本文件就是用来生产消息的,我们也直接来看代码
package.path = '/opt/openresty-docker/openresty/lua-dataagent/lib/resty/?.lua;'
local rabbitmq = require "rabbitmqstomp" local opts = {
username = 'guest',
password = 'guest',
vhost = '/'
}
local mq, err = rabbitmq:new(opts) if not mq then
ngx.log(,'cannot new mq')
ngx.log(,err)
return
end mq:set_timeout() -- connect to the rabbitmq on local machine
local ok, err = mq:connect('192.168.7.201', ) if not ok then
-- connect to other rabbitmq in cluster
ok, err = mq:connect('192.168.7.200', )
if not ok then
-- connect to last rabbitmq in cluster
-- put messages into errorLog
ngx.log(,'cannot connect mq')
ngx.log(,err)
return
end
end -- local msg = "d.g.test.com/gp.do?ac=s_publishgame&action=login&appId=133214321432&serverId=bj_server1&channel=test_gamecenter&accountId=q1132143214&playerId=q1132143214&tm=1458874365&first=1"
local msg = string.sub(ngx.var.request_uri,,-)
local result = string.gsub(msg,".*/","d.g.test.com/",) local send_receipt_id = ngx.now()*
local headers = {}
headers["destination"] = "/exchange/statistical/statistical.test"
headers["receipt"] = send_receipt_id
headers["app-id"] = "luaresty"
headers["persistent"] = "true"
headers["content-type"] = "application/plian" local ok, err = mq:send(result, headers)
if not ok then
ngx.log(,'cannot send mq')
ngx.log(,err)
return
end local ok, err = mq:set_keepalive(, )
if not ok then
ngx.log(,'cannot set_keepalive mq')
ngx.log(,err)
return
end -- ngx.say('success: ',msg)

  

5.配置RabbitMq

    RabbitMq比较好的一个资料站点:https://www.jianshu.com/p/124cda48e4ea

                     https://www.jianshu.com/p/61a90fba1d2a

交换机,statistical
               路由规则,statistical.test
               队列,test
               在rabbitmq中建好,就能往里发消息了

    添加 "交换机","路由规则","消息队列"

    //声明交换机

    rabbitmqctl eval 'rabbit_exchange:declare({resource, <<"/">>, exchange, <<"statistical">>}, topic, true, false, false, []).'

    //声明消息队列
    rabbitmqctl eval 'rabbit_amqqueue:declare({resource, <<"/">>, queue, <<"test">>}, true, false, [], none).'

    //绑定交换机,路由规则,消息队列
    rabbitmqctl eval 'rabbit_binding:add({binding, {resource, <<"/">>, exchange, <<"statistical">>}, <<"statistical.test">>, {resource, <<"/">>, queue, <<"test">>}, []}).'

  6.测试消息生产

   curl -i "http://192.168.7.200:8080/dataagent/v1/test/topic-sendtime-id/d.g.test.com/gp.do"

  重点提示:

  1.首先要理解集群的架构

  2.保证打点日志文件的存储空间足够大

  3.了解openresty

   openresty:是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

  4.要了解rabbitmq的相关知识,保证交换机,路由,消息队列的正常创建

  5.注意容器中配置文件和物理路径的映射关系

  6.lua脚本中,rabbitMq的地址一版是内网(局域网)地址

  7.swarm集群中,注意个集群节点 label 的自定义

  上面都有关于此问题的描述

  问题排查思路:

  1.查看nginx 日志来排查nginx异常日志

  2.理解架构途中消息的传递路径,顺着路近一步步追查

  

  好了,就写道这里,我是jerry百

   

Docker swarm结合Openresty部署rabbitmq集群的更多相关文章

  1. RabbitMQ系列(五)使用Docker部署RabbitMQ集群

    概述 本文重点介绍的Docker的使用,以及如何部署RabbitMQ集群,最基础的Docker安装,本文不做过多的描述,读者可以自行度娘. Windows10上Docker的安装 因为本人用的是Win ...

  2. Docker Swarm和Kubernetes在大规模集群中的性能比较

    Contents 这篇文章主要针对Docker Swarm和Kubernetes在大规模部署的条件下的3个问题展开讨论.在大规模部署下,它们的性能如何?它们是否可以被批量操作?需要采取何种措施来支持他 ...

  3. k8s集群部署rabbitmq集群

    1.构建rabbitmq镜像 RabbitMQ提供了一个Autocluster插件,可以自动创建RabbitMQ集群.下面我们将基于RabbitMQ的官方docker镜像,添加这个autocluste ...

  4. Docker环境下的前后端分离项目部署与运维(八)使用Docker部署RabbitMQ集群

    下载RabbitMQ镜像 镜像地址RabbitMQ Docker官方认证镜像地址:https://hub.docker.com/_/rabbitmq 安装命令安装之前,切记把Docker Hub设置为 ...

  5. docker部署rabbitmq集群

    docker版本:18.09.6 或以上 rabbitmq镜像版本:rabbitmq:3.9.5-management 一.拉镜像: docker pull rabbitmq:3.9.5-manage ...

  6. 在Docker中安装和部署MongoDB集群

    此文已由作者袁欢授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 在Docker中安装mongodb 采用的mongodb镜像:https://registry.hub.doc ...

  7. Linux 部署 rabbitMQ集群

    1. 部署Erlang 1.1 RabbitMQ依赖于Erlang,版本对应请查看 https://www.rabbitmq.com/which-erlang.html 1.2 下载安装Erlang ...

  8. Docker Swarm(十)Portainer 集群可视化管理

    前言 搭建好我们的容器编排集群,那我们总不能日常的时候也在命令行进行操作,所以我们需要使用到一些可视化的工具,Docker图形化管理提供了很多工具,有Portainer.Docker UI.Shipy ...

  9. 使用容器编排工具docker swarm安装clickhouse多机集群

    1.首先需要安装docker最新版,docker 目前自带swarm容器编排工具 2.选中一台机器作为master,执行命令sudo docker  swarm init [options] 3,再需 ...

随机推荐

  1. body 标签

    -图标 &nbsp(空格) -&gt(>) &lt(<) -p标签, 段落 <br \>  做换行 所有的标签分为: 块级标签: div(白板), H系 ...

  2. Simple2D-25 精灵动作

    精灵动画作用在精灵上,使精灵表现出动画效果.本文将详细说明如何创建一个简单的动作系统,暂时只有 4 中基本的动作——平移.旋转.缩放和 Alpha 变化,并且这些动作能够自由组合,组成串行动作或并行动 ...

  3. idea常用设置(持续更新)

    1.注释模板 Setting里找到live Templates (1)创建一个Templates Group (2)在Templates Group下创建Live Template 2.常用内置模板 ...

  4. PYTHON-进阶-装饰器小结,转载

    本文转载自:http://www.wklken.me/posts/2012/10/27/python-base-decorator.html 基本概念 具体概念自己google 装饰器是一个很著名的设 ...

  5. mysql 数据备份及数据迁移

    一.使用mysql数据导出进行备份时,会备份整个表的数据,有时候只想备份一部分数据,这个时候可以使用如下方法: 1. 使用insert into 和 select结合: insert into tal ...

  6. 前端编程工具WebStorm 10 工具的快捷使用方式

    1.如果是一个空白的文档,要想快速生成HTML的基本结构,可以写一个! 然后按一下tab键,如果是写的一个标签的名字,则会生成基本的标签结构. 2.h1{}:{}中写要显示的文本 3.h1[]:[]中 ...

  7. zabbix出现中文不能选的情况

    像这里一样,有些选项是选不了的,这个时候我们要做的第一步就是,找到这个配置文件. 如果不知道在哪里的话可以用find命令查找. sudo find / -name locales.inc.php 找到 ...

  8. windows本地blast

    详细可参考https://www.jianshu.com/p/2f125cdf8262:https://blog.csdn.net/qq_34296043/article/details/544277 ...

  9. frm和ibd恢复sql文件的操作

    情况:有mysql中data文件(仅仅一个数据库) 操作:frm和ibd恢复sql文件的操作 1.创建相同名字的库xxx 2.把ibdata1替换成原来的 3.把数据库xxx内内容全部替换为原来的 完 ...

  10. ssh-keygen生成私钥和公钥

    ssh-keygen生成私钥和公钥 例: 用户名:root 服务器地址:192.168.1.10 生成:ssh-keygen -t rsa -b 4096 -C“root@192.168.1.10” ...