rabbitmq集群第三篇--优化之我见

rabbitmq之优化畅谈

在本文中主要讲一下RabbitMQ集群的一些优化,因为近期公司业务系统因为连接不上MQ集群出现了很多问题,本文主要总结一些解决的方案:

1. RabbitMQ集群的架构:

??我们公司的RabbitMQ集群架构是我设计和实施的,当时也是参考了很多互联网上的架构文档;2台LVS服务器,3台MQ服务器。2台是内存节点,一台是磁盘节点;LVS服务器又通过keepalived实现了主从。VIP地址在主服务器上面,LVS负责分发客户端请求,通过Round-Robin轮训策略来负载。负载均衡器可以是LVS,也可以是haproxy.刚开始实施的时候我用的是Haproxy来实现负载均衡。后面因为Haproxy不支持来源Ip显示,每次在MQ管理页面排查问题都不知道是哪个客户端连接过来的,所以后面改成了LVS。

2. RabbitMQ集群的优化:

1. 修改heartbeat心跳超时时间:

??heartbeat通常用来检测通信的对端是否存活(未正常关闭socket连接而异常crash)。其基本原理是检测对应的socket连接上数据的收发是否正常,如果一段时间内没有收发数据,则向对端发送一个心跳检测包,如果一段时间内没有回应则认为心跳超时,即认为对端可能异常crash了。rabbitmq也不例外,heatbeat在客户端和服务端之间用于检测对端是否正常,即客户端与服务端之间的tcp链接是否正常。

1. 服务端的设置:

??heartbeat通常用来检测通信的对端是否存活(未正常关闭socket连接而异常crash)。其基本原理是检测对应的socket连接上数据的收发是否正常,如果一段时间内没有收发数据,则向对端发送一个心跳检测包,如果一段时间内没有回应则认为心跳超时,即认为对端可能异常crash了。rabbitmq也不例外,heatbeat在客户端和服务端之间用于检测对端是否正常,即客户端与服务端之间的tcp链接是否正常。
??heartbeat检测时间间隔可在配置文件rabbitmq.config中增加配置项{heartbeat,Timeout}进行配置,其中Timeout指定时间间隔,单位为秒.

[
{rabbit, [{tcp_listeners, [56720]}, {heartbeat,300}, {loopback_users, []}, {vm_memory_high_watermark, 0.6}]},
{rabbitmq_management, [{listener, [{port, 56721}]},{loopback_users, []}]},
{rabbitmq_tracing, [{username, "guest"}, {password, "guest111"}]}
].
2. JAVA客户端的设置:
ConnectionFactory cf = new ConnectionFactory();
// set the heartbeat timeout to 60 seconds
cf.setRequestedHeartbeat(60);

默认的心跳时间为60s,服务器端默认配置就是60s,也就是不配置也是60s.生产者或者消费者应用配置了其他心跳时间仍然不生效,因为协商的时候是以最小的配置为准。所以需要将服务器的心跳超时时间也改成300s才可以;

2. 配置rabbitmq的日志跟踪:

??有时候我们在连接rabbitmq的时候,会出现一些问题;比如生产者发送了消息到mq集群,但是消费者没有收到消息。然后生产者项目组说自己的配置没有问题,消费者也说自己的项目配置没有问题。这个时候就需要将rabbitmq的日志跟踪打开,实时查看具体的日志发送内容,排查业务问题;因为默认rabbitmq的应用日志非常简单,只有简单的连接IP,连接那个vhost信息等;开启的方式如下:

rabbitmq-plugins enable rabbitmq_tracing

通过rabbitmq命令行界面开启日志跟踪插件,然后通过web管理控制台针对单独的队列配置监控

需要配置要监控的vhost,里面一定要有guest账户的权限

选择tracing页面,配置要监控的vhost,输入监控的名称,选择JSON格式,选择要监控的队列,可以使用#.队列名的方式;

3. MQ消息的迁移:

?? 我们在使用rabbitmq的时候,有这种场景。因为我们有多数据中心,多个数据中心分别在不同的城市。为了减少专线的网络延迟,我们在每一个数据中心部署了一套MQ集群。有些业务因为某些原因,需要从A数据中心迁移到B数据中心,我需要在B数据中心创建MQ的账户和Vhost,迁移的时候如果队列里面还有未消费的消息,还需要将这些消息一同迁移过来。怎么迁移消息了,还是需要用到rabbitmq的插件;

# 首先在来源的MQ集群开启插件
rabbitmq-plugins enable rabbitmq_shovel
rabbitmq-plugins enable rabbitmq_shovel_management
rabbitmq-plugins enable rabbitmq_federation
rabbitmq-plugins enable rabbitmq_federation_management

安装好rabbitmq_shovel和rabbitmq_shovel_management两个插件之后,就可以在rabbitmq的管理页面查看到这两个插件,首先创建一个shovel.填入的信息主要包括要同步的vhost名称,起一个名字,来源mq服务器地址和队列,目标mq服务器地址和队列,其中要有对vhost授权的账户和密码。目标MQ集群要提前创建好vhost,配置的授权账户和密码,包括队列等。

还有一个插件Federation,这个插件一般用于实时同步消息的。我看官网上描述主要用于广域网上面的两个不同的MQ集群实时同步消息,我们公司用不到这种场景,所以没怎么深究;

4. MQ配置的备份和还原:

??MQ的备份可以由多种方式,可以通过web管理页面备份一个vhost的信息(包括队列、EXCHANGE、Bingding Key等),备份vhost一般在目标MQ集群要提前创建好用户、vhost、授权等,才可以恢复单独的vhost配置;也可以备份整个MQ的配置信息,用于还原一个空的MQ集群;如果目标MQ集群里面已经有配置,是追加而不是覆盖的方式;

导出一个vhost的配置,也可以选择all所有的配置导出

导入配置到另外一个vhost里面,也可以选择导入所有的配置,所有的配置导入建议在空的mq集群执行;不然容易造成配置冲突;

??但是这个是需要手工操作的,我们备份MQ的配置信息应该是每天定时备份才行,因为你也不知道哪一天MQ集群会出现故障;我写了一个shell脚本来实现每天定时备份MQ集群的配置信息。脚本的主要用途就是每天备份MQ的配置,并且备份完成之后会发邮件给我,告知我备份是否成功;脚本的内容如下:

#!/bin/bash
#
RABBITMQ_HOME=/usr/local/rabbitmq_server-3.6.9
PATH=$PATH:$RABBITMQ_HOME/sbin
export RABBITMQ_HOME PATH
ERLANG_HOME=/usr/local/erlang
PATH=$PATH:$ERLANG_HOME/bin
export ERLANG_HOME PATH
RABBITMQADMIN_HOME=/sbin
PATH=$PATH:$RABBITMQADMIN_HOME
export RABBITMQADMIN_HOME PATH

env_ip() {
array2=(
192.168.20.232
192.168.22.94
192.168.0.242
192.168.1.251
192.168.0.21
192.168.0.210
192.168.74.200
)
if [ $(ifconfig |grep eno16777984|wc -l) -eq 1 ];then
    mq_server_ip=${array2[1]}
    env_name=uat
    env="小小金融UAT环境MQ集群"
elif [ $(ifconfig eth1|awk ‘NR==2 {print $2}‘|awk -F ":" ‘{print $2}‘|grep 192.168.20|wc -l) -eq 1 ];then
    mq_server_ip=${array2[0]}
    env_name=sit
    env="小小金融SIT环境MQ集群"
elif [ $(ifconfig eth1|awk ‘NR==2 {print $2}‘|awk -F ":" ‘{print $2}‘|grep 192.168.0|wc -l) -eq 1 ];then
    mq_server_ip=${array2[2]}
    env_name=WHPRD01
    env="小小金融武汉PRD环境第一套MQ集群"
elif [ $(ifconfig eth1|awk ‘NR==2 {print $2}‘|awk -F ":" ‘{print $2}‘|grep 192.168.1|wc -l) -eq 1 ];then
    mq_server_ip=${array2[3]}
    env_name=WHPRD02
    env="小小金融武汉PRD环境第二套MQ集群"
elif [ $(ifconfig eth1|awk ‘NR==2 {print $2}‘|awk -F ":" ‘{print $2}‘|grep 192.168.0|egrep -v ‘[0-9][0-9][0-9]‘|wc -l) -eq 1 ];then
    mq_server_ip=${array2[4]}
    env_name=XXPRD
    env="小小金融深圳PRD环境MQ集群"
elif [ $(ifconfig eth1|awk ‘NR==2 {print $2}‘|awk -F ":" ‘{print $2}‘|grep 192.168.0|egrep  ‘[0-9][0-9][0-9]‘|wc -l) -eq 1 ];then
    mq_server_ip=${array2[5]}
    env_name=XXTTPRD
    env="小小金融深圳小小独立PRD环境MQ集群"
elif [ $(ifconfig -a|grep Bcast|awk -F "[ :]+" ‘{print $4}‘|grep 192.168.74|wc -l) -eq 1 ];then
    mq_server_ip=${array2[6]}
    env_name=XXTTUAT
    env="小小金融深圳小小独立UAT环境MQ集群"

fi
}
env_ip
mqadmin_user="admin"
mqadmin_pw="admin"
mqadmin_port="56721"
mq_config_backup_file="/data/mq_config_bak/${mq_server_ip}_mqconfigbak_$(date +%Y%m%d%H%M%S)"
if [ ! -d /data/mq_config_bak ];then
mkdir -p /data/mq_config_bak
fi
if [ "`ls -A /data/mq_config_bak`" != "" ];then
   rm -rf /data/mq_config_bak/*
fi

/sbin/rabbitmqadmin -H ${mq_server_ip} -P ${mqadmin_port} -u ${mqadmin_user} -p ${mqadmin_pw} export ${mq_config_backup_file} > /dev/null 2>&1
if [ "`ls -A /data/mq_config_bak`" != "" ];then
   scp -P 10022 -r /data/mq_config_bak/* [email protected]:/data/mq_config_bak/ &>/dev/null
   ssh -p 10022 [email protected] /bin/sh /.scripts/send_mqconfigbak.sh ${mq_server_ip} ${env}  &>/dev/null

fi

rabbitmqadmin使用api调用的工具,在mq的管理页面就可以直接下载;

5. 定时清理测试环境的MQ消息:

??这个脚本只能在测试环境运行,千万不要在生产环境运行。因为测试MQ集群经常会有消息堆积,并且测试环境的MQ集群配置比较低,经常会因为消息堆积而导致内存爆满,导致MQ服务器故障。因为MQ的消息没有消费的话都是存在于内存中;而生产环境的话,一般不能轻易清除消息。要和研发人员确认才行;

#!/bin/bash
#
echo > /tmp/queues.txt
echo > /tmp/queues2.txt
VHOST2=$(rabbitmqctl list_vhosts|grep -v "Listing vhosts")
for i in ${VHOST2[@]}
        do
          rabbitmqctl list_queues -p $i|grep -v "Listing queues"|awk ‘{$1="‘${i}‘ "$1;print}‘ >> /tmp/queues.txt
        done
cat /tmp/queues.txt|sort -rn -k3|sed ‘/^$/d‘ > /tmp/queues2.txt
file2="/tmp/queues2.txt"
cat $file2|while read line
    do
             queues_number=$(echo $line|awk ‘{print $NF}‘)
         if [ $queues_number -gt 5000 ];then
             queues_name=$(echo $line|awk ‘{print $2}‘)
             vhost_name=$(echo $line|awk ‘{print $1}‘)
             echo "$(date +%F-%H:%M:%S) the vhost ${vhost_name} include the queues ${queues_name} message number is ${queues_number} ,Because the number of messages exceeds 5000, the messages will be cleared" >> /tmp/purge_message.txt
             /usr/local/rabbitmq_server-3.6.9/sbin/rabbitmqctl purge_queue -p ${vhost_name} ${queues_name} >/dev/null 2>&1
         fi
    done

此脚本的主要用途就是当测试环境MQ集群的队列里面的消息数量超过5000,就会清理掉这些消息,并且写日志到固定文件中;然后把这个脚本放在linux的crontab里面每一个小时执行一次;

6. MQ客户端代码层的一些优化:

?? 前面讲到了MQ的一些优化,主要针对网络层的和架构层的。因为我的工作就是负责MQ服务器本身的稳定;关于研发代码层的优化包括如下:

  • 队列、消息都需要持久化;
  • 网络延迟是需要配置心跳的超时时间;
  • 需要有重连机制;
  • 生产者和消费者都需要有确认机制,比如配置ack等;
  • 重要队列还需要配置死信队列、镜像队列等;

7. 提供一个单机版MQ安装脚本:

#!/bin/bash
#
yum  -y install make gcc gcc-c++ kernel-devel m4 unixODBC unixODBC-devel openssl openssl-deetc
yum  -y install ncurses-devel
XXet -O /software/otp_src_19.0.tar.gz ftp://xxjrftp:Pass123$%^@192.168.20.27:9020/software/rabbitmq/otp_src_19.0.tar.gz
XXet -O /software/wxWidgets-3.0.2.tar.bz2 ftp://xxjrftp:Pass123$%^@192.168.20.27:9020/software/rabbitmq/wxWidgets-3.0.2.tar.bz2
XXet -O /software/rabbitmq-server-generic-unix-3.6.9.tar ftp://xxjrftp:Pass123$%^@192.168.20.27:9020/software/rabbitmq/rabbitmq-server-generic-unix-3.6.9.tar
cd /software
tar xzvf otp_src_19.0.tar.gz
cd otp_src_19.0
./configure --prefix=/usr/local/erlang --without-javac
value=$(echo $?)
if [ ${value} -eq 0 ];then
    make && make install
fi
echo -e "ERLANG_HOME=/usr/local/erlang\nPATH=\$PATH:\$ERLANG_HOME/bin\nexport ERLANG_HOME PATH\n" >>/etc/profile.d/erlang.sh
source /etc/profile.d/erlang.sh
yum -y install gtk2-devel binuti-devel mesa-libGL-devel mesa-libGLU-devel
cd /software && tar jxvf wxWidgets-3.0.2.tar.bz2  && cd wxWidgets-3.0.2
./configure --with-opengl --enable-debug --enable-unicode
value=$(echo $?)
if [ ${value} -eq 0 ];then
    make && make install
fi
cd /software
tar xf rabbitmq-server-generic-unix-3.6.9.tar
mv /software/rabbitmq_server-3.6.9 /usr/local
cd /usr/local
ln -sv rabbitmq_server-3.6.9   rabbitmq_server
echo -e "RABBITMQ_HOME=/usr/local/rabbitmq_server\nPATH=\$PATH:\$RABBITMQ_HOME/sbin\nexport RABBITMQ_HOME PATH\n" >>/etc/profile.d/rabbitmq.sh
source /etc/profile.d/rabbitmq.sh
XXet -O /etc/init.d/rabbitmq-server ftp://xxjrftp:Pass123$%^@192.168.20.27:9020/software/rabbitmq/rabbitmq-server
chmod +x /etc/init.d/rabbitmq-server
cd /etc/init.d
chkconfig --add rabbitmq-server
chkconfig rabbitmq-server on
mkdir -p /logs/rabbitmq
mkdir -p /var/run/rabbitmq
ln -s /usr/local/erlang/bin/erl /usr/bin/erl
XXet -O /usr/local/rabbitmq_server-3.6.9/etc/rabbitmq/enabled_plugins ftp://xxjrftp:Pass123$%^@192.168.20.27:9020/software/rabbitmq/enabled_plugins
XXet -O /usr/local/rabbitmq_server-3.6.9/etc/rabbitmq/rabbitmq.config ftp://xxjrftp:Pass123$%^@192.168.20.27:9020/software/rabbitmq/rabbitmq.config
service rabbitmq-server start
sleep 15
source /etc/profile
rabbitmqctl add_user admin 11111
rabbitmqctl set_user_tags admin administrator
rabbitmqctl change_password guest 222222
systemctl stop iptables
systemctl disable iptables

博文的更详细内容请关注我的个人微信公众号 “云时代IT运维”,本公众号旨在共享互联网运维新技术,新趋势; 包括IT运维行业的咨询,运维技术文档分享。重点关注devops、jenkins、zabbix监控、kubernetes、ELK、各种中间件的使用,比如redis、MQ等;shell和python等运维编程语言;本人从事IT运维相关的工作有十多年。2008年开始专职从事Linux/Unix系统运维工作;对运维相关技术有一定程度的理解。本公众号所有博文均是我的实际工作经验总结,基本都是原创博文。我很乐意将我积累的经验、心得、技术与大家分享交流!希望和大家在IT运维职业道路上一起成长和进步;

原文地址:https://blog.51cto.com/zgui2000/2427793

时间: 2024-11-07 10:50:30

rabbitmq集群第三篇--优化之我见的相关文章

你不知道的RabbitMQ集群架构全解

RabbitMQ系列文章 RabbitMQ在Ubuntu上的环境搭建 深入了解RabbitMQ工作原理及简单使用 RabbitMQ交换器Exchange介绍与实践 RabbitMQ事务和Confirm发送方消息确认--深入解读 使用Docker部署RabbitMQ集群 你不知道的RabbitMQ集群架构全解 前言 本文将系统的介绍一下RabbitMQ集群架构的特点.异常处理.搭建和使用中要注意的一些细节. 知识点 一.为什么使用集群? 二.集群的特点 三.集群异常处理 四.集群节点类型 五.集群

RabbitMQ配置负载均衡的意义及RabbitMQ集群是否可以随意使用

说明构建RabbitMQ集群来确保可用性和性能只是保障弹性消息通信基础架构的一半,另一半则是编写当集群节点发生故障时知道如何重连到集群的应用程序.处理到集群的重连有多种策略,这篇wiki所关注的这种是使用负载均衡来处理节点的选择.使用负载均衡的意义通过使用负载均衡,不仅可以减少应用程序处理节点故障代码的复杂性,又能确保在集群中连接的平均分布.但是即便使用了负载均衡,编写处理节点故障的应用程序也要比建立到集群的连接复杂的多,应用程序需要准备好重新创建交换器和队列以应对初始节点故障.为Rabbit做

RabbitMQ集群架构(HA)并结合.NET Core实操

原文:RabbitMQ集群架构(HA)并结合.NET Core实操 一.前言 已经一年没有更新博客了,由于公司事务比较多,并且楼主我也积极在公司项目中不断实践.net core.DDD以及Abp vnext,也积累了一些吐血经验,目前我在做一家在线教育公司负责智慧校园业务,所涉及到的数据一天达上百万,并且还需要对这些并发数据进行解析转化,在此次的过程中也涉及到了使用RabbitMQ进行业务的解耦和流量削峰来应对如此大量的请求:过程是痛苦的,但结果是美好的. 说到MQ,大家应该都听过,像Rabbi

基于Kubernetes(k8s)的RabbitMQ 集群

目前,有很多种基于Kubernetes搭建RabbitMQ集群的解决方案.今天笔者今天将要讨论我们在Fuel CCP项目当中所采用的方式.这种方式加以转变也适用于搭建RabbitMQ集群的一般方法.所以如果你想要设计自己的解决方案,你应该收集一些更符合你定制化需求的文章. 命名你的集群 在Kubernetes内部运行RabbitMQ集群会遇到一系列有意思的问题.最先会遇到的问题是为了使各个节点之间互相可见,我们应该如何命名各个节点.以下是一些符合规范的不同的命名方法: [email protec

RabbitMQ集群搭建

rabbitmq集群是通过erlang的分布式特性进行rabbitmq集群,各个rabbitmq的服务为相应的节点,每个节点都提供给客户端连接,进行消息的发送与接收. 环境:CentOS 6.8 64位 服务器:192.168.179.128 wangwq01 192.168.179.129 wangwq02 192.168.179.130 wangwq03 1. 主机域名解析 rabbitmq各节点之间通信使用域名,所以集群成员中所有主机名都要可解析,这里使用修改hosts文件来实现解析. 2

RabbitMQ集群

一.前言 线上的 RabbitMQ用的是单节点,前段时间由于机器内存不足,发生了OOM,业务受到了影响,故打算换成 RabbitMQ集群.RabbitMQ模式有三种,分别是:单一模式.普通模式.镜像模式,镜像模式才是RabbitMQ真正的HA方案,关于更详细的简绍,请移步到官网:http://www.rabbitmq.com/ha.html ,下面是关于RabbitMQ集群的部署过程: 二.环境 erlang版本: erlang-19.0.4-1.el7.centos.x86_64 rabbit

转载 Tomcat集群配置学习篇-----分布式应用

Tomcat集群配置学习篇-----分布式应用 现目前基于javaWeb开发的应用系统已经比比皆是,尤其是电子商务网站,要想网站发展壮大,那么必然就得能够承受住庞大的网站访问量:大家知道如果服务器访问量过大,就会出现服应用务器崩溃的情况,这个时候怎么办,难道就只能去重启服务器吗?好,如果是一般的小型公益网站到也无所谓,但如果是比如像大型航空公司售票等电子商务网站,每天每小时都有大量的订单业务,如果这些售票系统一旦崩溃后,再去重启,这些时间和客户的损失就直接会影响到航空公司的利益,这些损失如何去避

Rabbitmq集群高可用测试

Rabbitmq集群高可用 RabbitMQ是用erlang开发的,集群非常方便,因为erlang天生就是一门分布式语言,但其本身并不支持负载均衡. Rabbit模式大概分为以下三种:单一模式.普通模式.镜像模式 单一模式:最简单的情况,非集群模式. 没什么好说的. 普通模式:默认的集群模式. 对于Queue来说,消息实体只存在于其中一个节点,A.B两个节点仅有相同的元数据,即队列结构. 当消息进入A节点的Queue中后,consumer从B节点拉取时,RabbitMQ会临时在A.B间进行消息传

搭建高可用mongodb集群(三)—— 深入副本集内部机制

http://www.lanceyan.com/tech/mongodb_repset2.html 在上一篇文章<搭建高可用mongodb集群(二)—— 副本集> 介绍了副本集的配置,这篇文章深入研究一下副本集的内部机制.还是带着副本集的问题来看吧! 副本集故障转移,主节点是如何选举的?能否手动干涉下架某一台主节点. 官方说副本集数量最好是奇数,为什么? mongodb副本集是如何同步的?如果同步不及时会出现什么情况?会不会出现不一致性? mongodb的故障转移会不会无故自动发生?什么条件会