定制app开发Docker-Compose部署RabbitMQ

单一模式定制app开发即单机情况不做集群,定制app开发就单独运行一个rabbitmq而已。
普通模式默认模式,定制app开发以两个节点(rabbit01、rabbit02)定制app开发为例来进行说明。对于Queue来说,定制app开发消息实体只存在于其中一个节点rabbit01(或者rabbit02),rabbit01和rabbit02定制app开发两个节点仅有相同的元数据,定制app开发即队列的结构。定制app开发当消息进入rabbit01节点的Queue后,consumer从rabbit02定制app开发节点消费时,RabbitMQ会临时在rabbit01、rabbit02定制app开发间进行消息传输,把A定制app开发中的消息实体取出并经过B发送给consumer。所以consumer定制app开发应尽量连接每一个节点,定制app开发从中取消息。定制app开发即对于同一个逻辑队列,定制app开发要在多个节点建立物理Queue。否则无论consumer连rabbit01或rabbit02,出口总在rabbit01,定制app开发会产生瓶颈。当rabbit01定制app开发节点故障后,rabbit02定制app开发节点无法取到rabbit01定制app开发节点中还未消费的消息实体。定制app开发如果做了消息持久化,那么得等rabbit01节点恢复,定制app开发然后才可被消费;定制app开发如果没有持久化的话,就会产生消息丢失的现象。
镜像模式把需要的队列做成镜像队列,存在与多个节点属于RabbitMQ的HA方案。该模式解决了普通模式中的问题,其实质和普通模式不同之处在于,消息实体会主动在镜像节点间同步,而不是在客户端取数据时临时拉取。该模式带来的副作用也很明显,除了降低系统性能外,如果镜像队列数量过多,加之大量的消息进入,集群内部的网络带宽将会被这种同步通讯大大消耗掉。所以在对可靠性要求较高的场合中适用。

普通集群模式

1、-ce安装

[root@localhost ~]# vim /etc/yum.repos.d/docker-ce.repo[docker-ce-stable]name=Docker CE Stable - $basearchbaseurl=https://download.docker.com/linux/centos/$releasever/$basearch/stableenabled=1gpgcheck=0[root@localhost ~]# yum install docker-ce -y
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2、docker-compose安装

[root@localhost ~]# yum install -y python-pip[root@localhost ~]# pip install -U docker-compose[root@localhost ~]# docker-compose version
  • 1
  • 2
  • 3

3、先创建对应的挂载目录和shell脚本

mkdir -p /data/rabbitmqdocker network create --driver bridge --subnet 172.18.0.0/24 --gateway 172.18.0.1 my-net# 脚本如下cat /data/rabbitmq/init_rabbitmq.sh #!/bin/bash#reset first nodeecho "Reset first rabbitmq node."docker exec -it rabbitmq01 /bin/bash -c 'rabbitmqctl stop_app'docker exec -it rabbitmq01 /bin/bash -c 'rabbitmqctl reset'docker exec -it rabbitmq01 /bin/bash -c 'rabbitmqctl start_app'# build cluster(参数--ram表示设置为内存节点,忽略该参数默认为磁盘节点)echo "Starting to build rabbitmq cluster with two ram nodes."docker exec -it rabbitmq02 /bin/bash -c 'rabbitmqctl stop_app'docker exec -it rabbitmq02 /bin/bash -c 'rabbitmqctl reset'docker exec -it rabbitmq02 /bin/bash -c 'rabbitmqctl join_cluster --ram rabbit@rabbitmq01' docker exec -it rabbitmq02 /bin/bash -c 'rabbitmqctl start_app'docker exec rabbitmq03 /bin/bash -c 'rabbitmqctl stop_app'docker exec rabbitmq03 /bin/bash -c 'rabbitmqctl reset'docker exec rabbitmq03 /bin/bash -c 'rabbitmqctl join_cluster --ram rabbit@rabbitmq01'docker exec rabbitmq03 /bin/bash -c 'rabbitmqctl start_app'#check cluster statusecho "Check cluster status:"docker exec rabbitmq01 /bin/bash -c 'rabbitmqctl cluster_status'docker exec rabbitmq02 /bin/bash -c 'rabbitmqctl cluster_status'docker exec rabbitmq03 /bin/bash -c 'rabbitmqctl cluster_status'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

4、编写yml文件

version: '3'services:  rabbitmq01:    image: rabbitmq:3.10-management    container_name: rabbitmq01    ports:      - "15673:15672"      - "5673:5672"    hostname: rabbitmq01    restart: always    privileged: true#    build:#      context: .#      target: production    environment:      - TZ=Asia/Shanghai      - LANG=en_US.UTF-8      - RABBITMQ_DEFAULT_USER=zhe      - RABBITMQ_DEFAULT_PASS=123.com      # 集群通信(节点认证作用,集群部署需要同步该值,且值必须相同)      - RABBITMQ_ERLANG_COOKIE=rabbitcookie      # 群集中的节点名称必须唯一(在集群中各节点使用节点名称来识别和联系彼此)      - RABBITMQ_NODENAME:rabbitmq01      #如果系统使用完全限定的域名(FQDNs)作为主机名,则RabbitMQ节点和CLI工具必须配置为使用所谓的长节点名。对于服务器节点,这是通过将RABBITMQ_USE_LONGNAME环境变量设置为true来实现的。在不重置节点的情况下,无法将其从短名称切换到长名称。    volumes:      - /data/rabbitmq/rabbitmq01/:/var/lib/rabbitmq        # 防止log日志报failed to open log file      - /data/rabbitmq/rabbitmq01/:/var/log/rabbitmq    networks:      my-net:        ipv4_address: 172.18.1.10  rabbitmq02:    image: rabbitmq:3.10-management    container_name: rabbitmq02    ports:      - "15674:15672"      - "5674:5672"    hostname: rabbitmq02    restart: unless-stopped    privileged: true    environment:      # 集群通信      - TZ=Asia/Shanghai      - LANG=en_US.UTF-8      - RABBITMQ_ERLANG_COOKIE=rabbitcookie      - RABBITMQ_DEFAULT_USER=zhe      - RABBITMQ_DEFAULT_PASS=123.com      # 群集中的节点名称必须唯一(在集群中各节点使用节点名称来识别和联系彼此)      - RABBITMQ_NODENAME:rabbitmq02      #如果系统使用完全限定的域名(FQDNs)作为主机名,则RabbitMQ节点和CLI工具必须配置为使用所谓的长节点名。对于服务器节点,这是通过将RABBITMQ_USE_LONGNAME环境变量设置为true来实现的。在不重置节点的情况下,无法将其从短名称切换到长名称。      - RABBITMQ_CLUSTERED=true                   # 当前容器身份是从,会执行rabbitmqctl join_cluster命令加入到集群中去;       - RABBITMQ_CLUSTER_WITH=rabbit@rabbitmq01   # join的参数      - RABBITMQ_RAM_NODE=true                    # ram是以内存方式加入,忽略该参数默认为磁盘节点。      volumes:      - /data/rabbitmq/rabbitmq02/:/var/lib/rabbitmq      - /data/rabbitmq/rabbitmq02/:/var/log/rabbitmq #     - /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime:ro      # 如果要重建集群的话必须把rabbitmq lib目录中的/mnesi目录删除掉    depends_on:        # 从节点都依赖于主节点(防止关机导致容器集群失败)      - "rabbitmq01"    privileged: true    networks:      my-net:        ipv4_address: 172.18.1.20  rabbitmq03:    image: rabbitmq:3.10-management    container_name: rabbitmq03    ports:      - "15675:15672"      - "5675:5672"    hostname: rabbitmq03    restart: unless-stopped#    links:#      - rabbitmq01    environment:      # 集群通信      - TZ=Asia/Shanghai      - LANG=en_US.UTF-8      - RABBITMQ_ERLANG_COOKIE=rabbitcookie      - RABBITMQ_DEFAULT_USER=zhe      - RABBITMQ_DEFAULT_PASS=123.com      # 群集中的节点名称必须唯一(在集群中各节点使用节点名称来识别和联系彼此)      - RABBITMQ_NODENAME:rabbitmq03      #如果系统使用完全限定的域名(FQDNs)作为主机名,则RabbitMQ节点和CLI工具必须配置为使用所谓的长节点名。对于服务器节点,这是通过将RABBITMQ_USE_LONGNAME环境变量设置为true来实现的。在不重置节点的情况下,无法将其从短名称切换到长名称。      - RABBITMQ_CLUSTERED=true      - RABBITMQ_CLUSTER_WITH=rabbit@rabbitmq01      - RABBITMQ_RAM_NODE=true            volumes:      - /data/rabbitmq/rabbitmq03/:/var/lib/rabbitmq      - /data/rabbitmq/rabbitmq03/:/var/log/rabbitmq#      - /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime:ro    depends_on:      - "rabbitmq01"    privileged: true    networks:      my-net:        ipv4_address: 172.18.1.30networks:  my-net:    external: true
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101

5、加入集群

[root@localhost rabbitmq]# chmod +x init_rabbitmq.sh[root@localhost rabbitmq]# sh init_rabbitmq.sh					 #初始化镜像集群
  • 1
  • 2

到此为止,我们已经完成了普通模式集群的建立,启动了3个节点,1个磁盘节点和2个内存节点。但是如果磁盘节点挂掉后,数据就丢失了。所以我们这个集群方案需要进一步改造为镜像模式集群。
主从集群的不足: 默认情况下队列只位于主节点上,尽管他们可以从所有节点看到和访问,也就是说整个集群与主节点共存亡。
因此当主节点宕机时,无法进行自动的故障转移。
集群重启顺序
集群重启的顺序是固定的,并且是相反的
启动顺序:磁盘节点 => 节点
关闭顺序:内存节点 => 磁盘节点
最后关闭必须是磁盘节点,否则容易造成集群启动失败、数据丢失等异常情况
因为这里使用的是Docker-Compose所以我们让从节点都依赖于主节点,只有主节点启动后,从节点才会启动,关闭是自动先关闭的是从节点,注意我们一定不能直接关机,要输入docker-compose down把容器关了再关机否则容器造成集群失败~

depends_on:  - "rabbitmq1"
  • 1
  • 2

6、配置nginx反向代理到镜像集群通信

[root@localhost rabbitmq]# cd /data/nginx[root@localhost nginx]# vim nginx.confuser  nginx;worker_processes  2;error_log  /var/log/nginx/error.log warn;pid        /var/run/nginx.pid;events {    worker_connections  1024;}http {    include       /etc/nginx/mime.types;    default_type  application/octet-stream;    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '                      '$status $body_bytes_sent "$http_referer" '                      '"$http_user_agent" "$http_x_forwarded_for"';    access_log  /var/log/nginx/access.log  main;    sendfile        on;    #tcp_nopush     on;    keepalive_timeout  65;    #gzip  on;		proxy_redirect          off;	proxy_set_header        Host $host;	proxy_set_header        X-Real-IP $remote_addr;	proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;	client_max_body_size    10m;	client_body_buffer_size   128k;	proxy_connect_timeout   5s;	proxy_send_timeout      5s;	proxy_read_timeout      5s;	proxy_buffer_size        4k;	proxy_buffers           4 32k;	proxy_busy_buffers_size  64k;	proxy_temp_file_write_size 64k;	#rabbitmq管理界面	upstream rabbitManage {		server 192.168.235.13:15673;		server 192.168.235.13:15674;		server 192.168.235.13:15675;	}	server {        listen       15672;        server_name  192.168.235.13;         location / {              proxy_pass   http://rabbitManage;            index  index.html index.htm;          }      }}# rabbitmq通信stream{	upstream rabbitTcp{        server 192.168.235.13:5673;        server 192.168.235.13:5674;	    server 192.168.235.13:5675;    }    server {        listen 5672;        proxy_pass rabbitTcp;    }}[root@localhost nginx]# docker run -it -d --name nginxRabbitmq -v /data/nginx/nginx.conf:/etc/nginx/nginx.conf  --privileged --net=my-net nginx:1.20.2
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75

7、部署portainer容器界面化管理

docker run -itd -p 9000:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --name portainer docker.io/portainer/portainer
  • 1

访问rabbitmq的管理页面
访问: http://IP:15672 默认账号密码:zhe:123.com

镜像模式集群改造

镜像集群就是在主从集群的基础上,添加相应策略,将主节点消息队列中的信息备份到其它节点上,主节点宕机时,对整个集群不产生影响,使集群可以高可用。
镜像队列是Rabbit2.6.0版本带来的一个新功能,允许内建双活冗余选项,与普通队列不同,镜像节点在集群中的其他节点拥有从队列拷贝,一旦主节点不可用,最老的从队列将被选举为新的主队列。
镜像队列
如果 RabbitMQ 集群中只有一个 Broker 节点,那么该节点的失效将导致整体服务的临时性不可用,并且也可能会导致消息的丢失。可以将所有消息都设置为持久化,并且对应队列的durable属性也设置为true,但是这样仍然无法避免由于缓存导致的问题:因为消息在发送之后和被写入磁盘井执行刷盘动作之间存在
一个短暂却会产生问题的时间窗。通过 publisherconfirm 机制能够确保客户端知道哪些消息己经存入磁盘,
尽管如此,一般不希望遇到因单点故障导致的服务不可用。
引入镜像队列(Mirror Queue)的机制,可以将队列镜像到集群中的其他 Broker 节点之上,如果集群中的一个节点失效了,队列能自动地切换到镜像中的另一个节点上以保证服务的可用性。

添加策略(可以在创建队列之前添加,也可以创建队列之后添加)

参考官方文档:
策略模板([]表示可选参数,<>表示必穿参数)

rabbitmqctl set_policy [-p <vhost>] [--priority <priority>] [--apply-to <apply-to>] <name> <pattern> <definition>#参数						说明-p vhost			对指定的vhost进行设置name				policy的名称pattern				queue的匹配模式(正则表达式)definition			镜像定义:包含三个部分ha-mode,ha-params,ha-sync-mode					ha-mode:指明镜像队列的模式。  all:集群中所有节点进行镜像; exactly:在指定个数节点进行镜像,节点个数由ha-params指定;  nodes:在指定节点进行镜像,节点名称由ha-params指定					ha-params: ha-mode模式需要用到的参数					ha-sync-mode: 消息的同步方式(automatic,manual)priority			policy的优先级,当有多个策略指定同一个队列时,优先级高的策略生效
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

添加策略实例

rabbitmqctl set_policy h**a-11 '^11' '{"ha-mode":"all","ha-sync-mode":"automatic"}'说明:策略正则表达式为 "^" 表示匹配所有队列名称, ^11 :表示匹配hello开头的队列以上策略的添加,删除,查看都可以在web UI 界面操作。
  • 1
  • 2
  • 3
  • 4

镜像队列的工作原理

在某种程度上你可以将镜像队列视为拥有一个隐藏的fanout交换器,它指示着信道将消息分发到从队列上。

设置镜像队列

设置镜像队列命令:rabbitmqctl set_policy 名称 匹配模式(正则) 镜像定义, 例如设置名称为ha的镜像队列,匹配所有名称是amp开头的队列都存储在2个节点上的命令如下:
docker exec -it rabbitmq01 bash

设置策略匹配所有名称是amp开头的队列都存储在2个节点上
rabbitmqctl set_policy -p / ha “^amp*” ‘{“ha-mode”:“exactly”,“ha-params”:2}’
或者
设置策略匹配所有名称的队列都进行高可用配置
rabbitmqctl set_policy -p / ha “^” ‘{“ha-mode”:“all”,“ha-sync-mode”:“automatic”}’

查询策略

rabbitmqctl list_policies -p / #查看vhost下的所有的策略(policies)可以看出设置镜像队列,一共有四个参数,每个参数用空格分割。参数一		策略名称,可以随便填,此外我们命名为ha(高可用)参考二		-p / 设置哪个虚拟主机,可以使用rabbitmqctl list_policies -p / 	查看vhost下所有的策略policies参数三		队列名称的匹配规则,使用正则表达式表示参数四		为镜像队列的主体规则,是json字符串,分为三个属性:ha-mode | ha-params | ha-sync-mode,分别的解释如下:✔ ha-mode 镜像模式,分类all/exactly/nodes,all存储在所有节点、exactly存储x个节点、节点的个数由ha-params指定;nodes指定存储的节点上名称,通过ha-params指定✔ ha-params		作为参数,为ha-mode的补充;✔ ha-sync-mode  镜像消息同步方式:automatic(自动),manually(手动)--》至此rabbitmq集群算是搭建完毕。rabbitmqctl list_policies		# 查看镜像队列rabbitmqctl clear_policy		# 删除镜像队列
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

总结

阿里云 消息队列 MQ 消息队列(Message Queue,简称 MQ)是构建分布式互联网应用的基础设施,通过 MQ 实现的松耦合架构设计可以提高系统可用性以及可扩展性,是适用于现代应用的最佳设计方案。如有消息队列 RocketMQ 版 阿里巴巴官方指定消息产品,成熟、稳定、先进的技术体系打造金融级消息服务,感受双十一产品的完美体验。
腾讯云消息队列 TDMQ(Tencent Distributed Message Queue,简称TDMQ)是一款基于 Apache 顶级开源项目 Pulsar 自研的金融级分布式消息中间件。其计算与存储分离的架构设计,使得它具备极好的云原生和 Serverless 特性,用户按量使用,无需关心底层资源。它拥有原生 Java 、 C++、Python、GO 等多种 API,同时支持 kafka 协议以及 HTTP 协议方式接入,可为分布式应用系统提供异步解耦和削峰填谷的能力,具备互联网应用所需的海量消息堆积、高吞吐、可靠重试等特性。TDMQ 目前已应用在腾讯计费绝大部分场景,包括支付主路径、实时对账、实时监控、大数据实时分析等方面。

其他问题

♥ 如出现该过期警告:RABBITMQ_ERLANG_COOKIE对env变量的支持已被弃用,将在未来的版本中移除。Use the $HOME/.erlang.cookie file or the --erlang-cookie switch instead.

root@rabbitmq02:/# rabbitmqctl join_cluster --ram rabbit@rabbitmq01RABBITMQ_ERLANG_COOKIE env variable support is deprecated and will be REMOVED in a future version. Use the $HOME/.erlang.cookie file or the --erlang-cookie switch instead.Clustering node rabbit@rabbitmq02 with rabbit@rabbitmq01Error:incompatible_feature_flags原因:镜像版本不一致导致
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

♥ 配置相同Erlang Cookie
有些特殊的情况,比如已经运行了一段时间的几个单个物理机,我们在之前没有设置过相同的Erlang Cookie值,现在我们要把单个的物理机部署成集群,实现我们需要同步Erlang的Cookie值。
1.为什么要配置相同的erlang cookie?
因为RabbitMQ是用Erlang实现的,Erlang Cookie相当于不同节点之间相互通讯的秘钥,Erlang节点通过交换Erlang Cookie获得认证。
2.Erlang Cookie的位置
要想知道Erlang Cookie位置,首先要取得RabbitMQ启动日志里面的home dir路径作为根路径。使用:“docker logs 容器名称”查看。
所以Erlang Cookie的全部路径就是“/var/lib/rabbitmq/.erlang.cookie”。
注意:每个人的erlang cookie位置可能不同,一定要查看自己的home dir路径。
3.复制Erlang Cookie到其他RabbitMQ节点
获取到第一个RabbitMQ的Erlang Cookie之后,只需要把这个文件复制到其他RabbitMQ节点即可。
物理机和容器之间复制命令如下:
▷ 容器复制文件到物理机:docker cp 容器名称:容器目录 物理机目录
▷ 物理机复制文件到容器:docker cp 物理机目录 容器名称:容器目录
设置Erlang Cookie文件权限:“chmod 600 /var/lib/rabbitmq/.erlang.cookie”。
Don’t give up your dreams because there is no applause.

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发