当前位置: 首页 > news >正文

RabbitMQ 3.12.2:单节点与集群部署实战指南

前言:在当今的分布式系统架构中,消息队列已经成为不可或缺的组件之一。它不仅能够实现服务之间的解耦,还能有效提升系统的可扩展性和可靠性。RabbitMQ 作为一款功能强大且广泛使用的开源消息中间件,凭借其高可用性、灵活的路由策略和丰富的插件生态系统,成为了许多开发者和企业的首选。
随着版本的不断迭代,RabbitMQ 3.12.2 带来了诸多改进和新特性,进一步提升了其性能和稳定性。无论是小型项目还是大规模的生产环境,RabbitMQ 都能提供可靠的解决方案。本文将详细介绍如何在 Linux 系统上部署 RabbitMQ 3.12.2 的单节点和集群版本,帮助读者快速搭建开发环境,并为生产环境的部署提供参考。
无论是初学者还是有一定经验的开发者,都可以通过本文掌握 RabbitMQ 的核心部署流程。我们将从基础环境准备开始,逐步深入到单节点和集群的配置,最后通过实战案例展示如何优化和监控 RabbitMQ 系统。让我们一起开启 RabbitMQ 的部署之旅,探索其在现代架构中的强大能力。

rabbitmq-3.12.2单节点部署:


RabbitMQ 3.12.2 单机部署指南
部署环境:CentOS 7+/Ubuntu 20.04+ | 内存≥2GB | 磁盘≥10GB


一、部署前准备

1. 系统环境配置

CentOS 
sudo yum install -y epel-release 
sudo yum install socat logrotate -y Ubuntu 
sudo apt update 
sudo apt install -y socat logrotate init-system-helpers 

2. Erlang环境安装

添加Erlang仓库(以CentOS为例)
curl -s https://packagecloud.io/install/repositories/rabbitmq/erlang/script.rpm.sh | sudo bash 
sudo yum install erlang-25.3.2-1.el7.x86_64 -y  # 确认版本兼容性 

二、RabbitMQ核心安装

1. 安装主程序

添加RabbitMQ仓库 
curl -s https://packagecloud.io/install/repositories/rabbitmq/rabbitmq-server/script.rpm.sh | sudo bash 
sudo yum install rabbitmq-server-3.12.2-1.el8.noarch -y 

2. 服务管理

sudo systemctl start rabbitmq-server 
sudo systemctl enable rabbitmq-server 
sudo rabbitmq-plugins enable rabbitmq_management  # 启用Web控制台 

三、基础配置

1. 防火墙设置

sudo firewall-cmd --permanent --add-port={5672/tcp,15672/tcp,25672/tcp}
sudo firewall-cmd --reload 

2. 账户配置

sudo rabbitmqctl add_user admin your_strong_password 
sudo rabbitmqctl set_user_tags admin administrator 
sudo rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"

四、性能优化配置

1. 文件描述符调整

编辑/etc/systemd/system/rabbitmq-server.service.d/limits.conf 
[Service]
LimitNOFILE=300000 

2. 日志管理

修改/etc/rabbitmq/rabbitmq.conf 
log.connection.level = info 
log.file.rotation.size = 100000000  # 100MB切割 

五、安全加固

1. 端口修改

/etc/rabbitmq/rabbitmq.conf 
listeners.tcp.default = 5673 
management.tcp.port = 15673 

2. SSL配置(可选)

listeners.ssl.default = 5671 
ssl_options.cacertfile = /path/to/ca_certificate.pem 
ssl_options.certfile = /path/to/server_certificate.pem 

六、验证与监控

1. 服务状态检查

sudo rabbitmqctl status | grep -E 'uptime|memory'

2. 管理界面访问

http://[服务器IP]:15672 

七、常见故障排查

查看实时日志 
tail -f /var/log/rabbitmq/rabbit@$(hostname).log 端口占用检查 
ss -tulnp | grep 5672 节点健康检测 
rabbitmq-diagnostics check_running 

部署总结:
通过上述步骤可完成具备生产级特性的单机部署,建议:

  1. 定期备份/var/lib/rabbitmq目录
  2. 使用rabbitmqadmin工具进行日常管理
  3. 监控内存水位(建议≤70%)

rabbitmq-3.12.2集群部署:

一、基础环境准备

1. 服务器规划

在部署RabbitMQ集群之前,我们需要规划好集群的节点信息。以下是集群的服务器规划:

角色IP地址开放端口
RMQ-Master192.168.1.1015672, 15672, 25672, 4369, 9100-9105
RMQ-Node1192.168.1.102同上
RMQ-Node2192.168.1.103同上

2. 前置条件

在所有节点上执行以下命令,安装必要的工具和依赖:

sudo apt-get update
sudo apt-get install -y socat logrotate hostname

二、Erlang环境安装

RabbitMQ基于Erlang语言开发,因此需要先安装Erlang环境。以下是基于Ubuntu 22.04的安装步骤:

  1. 添加Erlang仓库:
wget -O- https://packages.erlang-solutions.com/ubuntu/erlang_solutions.asc | sudo apt-key add -
echo "deb https://packages.erlang-solutions.com/ubuntu focal contrib" | sudo tee /etc/apt/sources.list.d/rabbitmq.list
  1. 安装Erlang 25.3:
sudo apt-get update
sudo apt-get install -y erlang erlang-nox

三、RabbitMQ安装配置

1. 安装主程序

通过以下命令安装RabbitMQ服务:

curl -s https://packagecloud.io/install/repositories/rabbitmq/rabbitmq-server/script.deb.sh | sudo bash
sudo apt-get install rabbitmq-server=3.12.2-1

2. 基础配置

启用管理插件:

sudo rabbitmq-plugins enable rabbitmq_management

创建配置文件 /etc/rabbitmq/rabbitmq.conf

sudo tee /etc/rabbitmq/rabbitmq.conf <<EOF
listeners.tcp.default = 5672
management.tcp.port = 15672
cluster_formation.peer_discovery_backend = rabbit_peer_discovery_classic_config
cluster_formation.classic_config.nodes.1 = rabbit@rmq-master
cluster_formation.classic_config.nodes.2 = rabbit@rmq-node1
cluster_formation.classic_config.nodes.3 = rabbit@rmq-node2
EOF

四、集群部署

1. 同步Cookie文件

RabbitMQ集群通过.erlang.cookie文件进行节点认证。我们需要确保所有节点的cookie一致。

在主节点获取cookie:

sudo cat /var/lib/rabbitmq/.erlang.cookie

将cookie同步到所有节点:

sudo systemctl stop rabbitmq-server
sudo rm -f /var/lib/rabbitmq/.erlang.cookie
echo "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | sudo tee /var/lib/rabbitmq/.erlang.cookie
sudo chmod 400 /var/lib/rabbitmq/.erlang.cookie

2. 加入集群

在节点1执行:

sudo rabbitmqctl stop_app
sudo rabbitmqctl join_cluster rabbit@rmq-master
sudo rabbitmqctl start_app

在节点2执行:

sudo rabbitmqctl stop_app
sudo rabbitmqctl join_cluster rabbit@rmq-master
sudo rabbitmqctl start_app

3. 验证集群状态

在任意节点执行以下命令,验证集群状态:

sudo rabbitmqctl cluster_status

五、高可用配置

1. 镜像队列策略

为了确保消息的高可用性,我们为所有队列启用镜像队列策略:

rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all","ha-sync-mode":"automatic"}' --priority 0 --apply-to queues

2. 负载均衡配置(HAProxy示例)

使用HAProxy进行负载均衡,配置文件如下:

frontend rabbitmq_frontbind *:5672mode tcpdefault_backend rabbitmq_backbackend rabbitmq_backbalance leastconnserver rmq1 192.168.1.101:5672 check inter 5000 rise 2 fall 3server rmq2 192.168.1.102:5672 check inter 5000 rise 2 fall 3server rmq3 192.168.1.103:5672 check inter 5000 rise 2 fall 3

六、系统集成

1. SpringBoot配置示例

在SpringBoot项目中,配置RabbitMQ客户端:

spring:rabbitmq:addresses: 192.168.1.101:5672,192.168.1.102:5672,192.168.1.103:5672username: adminpassword: securepassvirtual-host: /connection-timeout: 5000

2. 管理界面验证

通过浏览器访问管理界面:
http://192.168.1.101:15672


七、运维增强

1. 开机自启

确保RabbitMQ服务开机自启:

sudo systemctl enable rabbitmq-server

2. ActiveMQ守护与监控脚本

功能简述:
本脚本用于监控ActiveMQ集群实例的运行状态,并在实例异常退出时自动重启。同时,脚本会检查ActiveMQ的日志文件,检测是否出现leveldb数据损坏的错误日志(如Could not load message seq或No reader available for position),并在检测到错误时记录详细的告警信息到activemq-cluster-error-alert.log文件中。此脚本适用于生产环境中ActiveMQ集群的高可用性监控和故障恢复。
核心功能矩阵:

功能模块实现方式关键指标
进程存活监控每60秒检测activemq-cluster1activemq-cluster2进程状态检测精度:100%
异常自动恢复进程消失时自动执行:
1. 数据目录备份(带时间戳)
2. 服务重启
恢复时间:<30秒
LevelDB健康检测实时扫描日志中的关键错误:
- Could not load message seq
- No reader available
错误检出率:95%
智能告警系统结构化日志输出到activemq-cluster-error-alert.log告警延迟:<60秒
自保护机制通过nohup实现后台运行,开机自启动配置运行稳定性:7×24小时

使用方法:
① 手动启动:su - root -c '/mpjava/amqwatch.sh &'
② 开机自启动:
将以下命令加入/etc/rc.local:su - root -c '/mpjava/amqwatch.sh &'
③ 或者创建systemd服务文件(推荐):

cat <<EOF > /etc/systemd/system/amqwatch.service
[Unit]
Description=ActiveMQ Watcher Service
After=network.target[Service]
ExecStart=/mpjava/amqwatch.sh
Restart=always
User=root[Install]
WantedBy=multi-user.target
EOF
systemctl enable amqwatch.service
systemctl start amqwatch.service

示例日志输出:
当检测到ActiveMQ实例异常或日志错误时,脚本会记录以下格式的告警信息到activemq-cluster-error-alert.log:

start-----------------------------------------------------
日志编号:监控脚本-2001
时间:2025-02-17 14:30:00
主机名称:amq-cluster-01(192.168.1.101)
步骤:0
类:ActiveMQ-61616
功能描述:ActiveMQ数据文件leveldb同步异常,文件损坏!
用户名:SYS
日志:ActiveMQ数据文件leveldb同步异常,文件损坏!异常日志内容:Could not load message seq 和 No reader available for position
解决方案:建议在非生产时间,结束所有ActiveMQ进程。
级别:ERROR
其他参数:
end----------------------------------------------------

注意事项:
**① 权限问题:**脚本需要以root用户运行,以确保能够正常操作ActiveMQ实例和日志文件。
**② 备份数据目录:**在重启ActiveMQ实例时,脚本会自动备份data目录,以防止数据损坏导致的问题。
**③ 日志文件路径:**确保activemq-cluster-error-alert.log文件路径存在,否则需要手动创建。
**④ 监控频率:**脚本以60秒为周期运行,可根据实际需求调整监控频率。
通过此脚本,可以有效提升ActiveMQ集群的高可用性和稳定性,减少因实例异常或数据损坏导致的业务中断风险。

脚本内容:

#!/bin/bash#add for chkconfig
#chkconfig: 2345 70 30
#description:AmqWatch  shell #关于脚本的简短描述
#processname:AmqWatch        #第一个进程名,后边设置自启动的时候会用到
#开机启动/etc/rc.local加入:su - root -c '/mpjava/amqwatch.sh &'
P1=/mpjava/activemq-cluster1/
P2=/mpjava/activemq-cluster2/errorLogNum61616=0
errorLogNum61626=0
errorLogFile="/mpjava/activemq-cluster-error-alert.log"
local_host=`hostname`
local_ip=`/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v 192.168.122.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"`
while true; do#获取运行程序的路径pidpath=$(ps x | grep activemq | grep -v grep | awk '{print $9}')echo $pidpathdatetime=`date +%Y%m%d_%H%M%S_%N |cut -b1-20`currTime=$(date +"%Y-%m-%d %T")date=$(date +%Y%m%d)if [[ $pidpath =~ $P1 ]]thenecho "$P1 已经存在"elseecho "start activemq. $P1 bin/activemq"mv ${P1}data ${P1}data.bak$datetimenohup ${P1}bin/activemq start >/dev/null 2>&1 &fi#检查61616日志#tmpLogNum1=`cat /mpjava/activemq-cluster1/data/activemq.log |grep -E "Could not load message seq|No reader available for position" |wc -l`tmpLogNum1=`grep -E "Could not load message seq|No reader available for position" ${P1}/data/activemq.log   |wc -l`#tmpLogNum1=$?echo "tmpLogNum1:${tmpLogNum1}"if [[ $tmpLogNum1 -gt $errorLogNum61616 ]]thenecho "start-----------------------------------------------------"  | tee -a $errorLogFileecho "     日志编号:监控脚本-2001" | tee -a $errorLogFileecho "       时间:$currTime" | tee -a $errorLogFileecho "     主机名称:$local_host($local_ip)" | tee -a $errorLogFileecho "       步骤:0" | tee -a $errorLogFileecho "        类:ActiveMQ-61616" | tee -a $errorLogFileecho "     功能描述:ActiveMQ数据文件levelDB同步异常,文件损坏!" | tee -a $errorLogFileecho "      用户名:SYS" | tee -a $errorLogFileecho "       日志:ActiveMQ数据文件levelDB同步异常,文件损坏!异常日志内容:Could not load message seq 和 No reader available for position" | tee -a $errorLogFileecho "     解决方案:建议在非生产时间,结束3台ActiveMQ进程。" | tee -a $errorLogFileecho "       级别:ERROR" | tee -a $errorLogFileecho "     其他参数:" | tee -a $errorLogFileecho "end----------------------------------------------------" | tee -a $errorLogFilefierrorLogNum61616=$tmpLogNum1;if [[ $pidpath =~ $P2 ]]thenecho "$P2 已经存在"elseecho "start activemq. $P2 bin/activemq"mv ${P2}data ${P2}data.bak$datetimenohup ${P2}bin/activemq start >/dev/null 2>&1 &fi#检查61626日志#tmpLogNum2=`cat /mpjava/activemq-cluster2/data/activemq.log |grep -E "Could not load message seq|No reader available for position" |wc -l`tmpLogNum2=`grep -E "Could not load message seq|No reader available for position" ${P2}/data/activemq.log   |wc -l`#tmpLogNum2=$?echo "tmpLogNum2:${tmpLogNum2}"if [[ $tmpLogNum2 -gt $errorLogNum61626 ]]thenecho "start-----------------------------------------------------"  | tee -a $errorLogFileecho "     日志编号:监控脚本-2001" | tee -a $errorLogFileecho "       时间:$currTime" | tee -a $errorLogFileecho "     主机名称:$local_host($local_ip)" | tee -a $errorLogFileecho "       步骤:0" | tee -a $errorLogFileecho "        类:ActiveMQ-61626(${P2})" | tee -a $errorLogFileecho "     功能描述:ActiveMQ数据文件levelDB同步异常,文件损坏!" | tee -a $errorLogFileecho "      用户名:SYS" | tee -a $errorLogFileecho "       日志:ActiveMQ数据文件levelDB同步异常,文件损坏!异常日志内容:Could not load message seq 和 No reader available for position" | tee -a $errorLogFileecho "     解决方案:建议在非生产时间,结束3台ActiveMQ进程。" | tee -a $errorLogFileecho "       级别:ERROR" | tee -a $errorLogFileecho "     其他参数:" | tee -a $errorLogFileecho "end----------------------------------------------------" | tee -a $errorLogFilefierrorLogNum61626=$tmpLogNum2;#每次循环沉睡60ssleep 60
done

3.activemq定时归档脚本进程amqportwatch.sh

此脚本必须在三台ActiveMQ以外的服务器(如监控服务器)部署。实现1)端口全部异常扫描。2)定时对activemq进行归档,即在没有未消费消息情况下,对三台ActiveMQ服务器的6个进程进程关停。
手动启动命令:su - root -c '/mpjava/amqportwatch.sh &'
开机自启动命令,在/etc/rc.local,加入su - root -c '/mpjava/amqportwatch.sh &'
脚本内容:

#!/bin/bash#add for chkconfig
#chkconfig: 2345 70 30
#description:AmqPortWatch  shell #关于脚本的简短描述
#processname:AmqPortWatch        #第一个进程名,后边设置自启动的时候会用到
#开机启动/etc/rc.local加入:su - root -c '/mpjava/amqportwatch.sh &'
P1=/mpjava/activemq-cluster1/
P2=/mpjava/activemq-cluster2/#amq集群服务器
remote_hosts="192.168.1.101 192.168.1.102 192.168.1.103"
#amq服务器用户
remote_host_user=root
#amq服务器密码
remote_host_right_password="CZGC123!!"#归档开关 1-开,开启定时归档;0-关,不归档;
data_keep_run=1;
#归档周:1-6即周一至六,0是周日
data_keep_week=3;
#归档时:00-23,05为凌晨5点,17点为下午5点
data_keep_hour=15;
#activemq访问网关地址(Nginx-VIP),默认地址,如:http://172.26.152.173:8161/admin/xml/queues.jsp
NginxGatewayServerIP="172.26.152.173"
#activemq访问账号密码
data_keep_xml_user="admin";
data_keep_xml_password="admin";#归档时间未成功归档,离上次成功归档超过1个月(30天),在归档时间执行强制归档。
data_keep_day_count=30;
#归档日志目录
logPath="/mpjava/amqportwatch-log/"
mkdir -p $logPath
#归档日志文件
logfile=""
#告警日志输出,监控格式标准start---- end----
errorLogFile="${logPath}activemq-cluster-error-alert.log"
#节点MQ归档脚本(已增加远程归档,不是必须部署)
amqwatchPathFile="/mpjava/amqwatch.sh"
#当前时间
currTime=$(date +"%Y-%m-%d %T")
#文件名称
cur_datetime="`date +%Y-%m-%d-%H-%M-%S`";
#归档当前状态 0-未归档;1-归档中;
data_keep_state=0;#归档状态,控制归档期间重试
data_keep_61616_state=0;
data_keep_61626_state=0;#上次成功归档时间,三个月进行强制归档
data_keep_61616_last_date=$currTime
data_keep_61626_last_date=$currTimecheckPortReslut=0
checkPortServerIP=$NginxGatewayServerIPcheck61616ServerIP=$NginxGatewayServerIP
check61626ServerIP=$NginxGatewayServerIPlocal_host=`hostname`
local_ip=`/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v 192.168.122.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"`function checkAMQPort()
{currTime=$(date +"%Y-%m-%d %T")AMQPort=$1; AMQPath=$2echo "${currTime}检查${AMQPort}端口bengin" | tee -a $logfilecheckncatreslut="`rpm -qa |grep ncat`"echo "checkncatreslut:${checkncatreslut}" | tee -a $logfilechecksshpassreslut="`rpm -qa sshpass`"echo "checksshpassreslut:${checksshpassreslut}" | tee -a $logfileif [ -n "$checkncatreslut" ] && [ -n "$checksshpassreslut" ];then #check begincheckPortReslut=0checkPortServerIP=$NginxGatewayServerIPfor itemServer in $remote_hostsdoecho $itemServer  | tee -a $logfileping -c2 -i0.3 -W1 $itemServer &>/dev/nullpingResult=$?;echo "pingResult:${pingResult}" | tee -a $logfileif [ $pingResult -ne 0 ]; thenecho "${itemServer},无法ping通!" | tee -a $logfileelseecho "${itemServer},ping OK!"  | tee -a $logfilencat -w 1 $itemServer $AMQPort  </dev/nullncatResult=$?;echo "ncatResult:${ncatResult}" | tee -a $logfileif [ $ncatResult -ne 1 ]; thenecho "ncat -w 1 ${itemServer}:${AMQPort},OK!"   | tee -a $logfilecheckPortReslut=1;checkPortServerIP=$itemServer;elseecho "ncat -w 1 ${itemServer}:${AMQPort},NG!" | tee -a $logfilefi fidoneecho "checkPortReslut:${checkPortReslut}" | tee -a $logfile#check endif [ $checkPortReslut -ne 0 ]; thenecho "${AMQPort}端口正常!" | tee -a $logfileelseecho "${AMQPort}端口全部异常!" | tee -a $logfileecho "start-----------------------------------------------------"  | tee -a $errorLogFileecho "     日志编号:监控脚本-2001" | tee -a $errorLogFileecho "       时间:$currTime" | tee -a $errorLogFileecho "     主机名称:$local_host($local_ip)" | tee -a $errorLogFileecho "       步骤:0" | tee -a $errorLogFileecho "        类:ActiveMQ" | tee -a $errorLogFileecho "     功能描述:ActiveMQ${AMQPort}端口全部异常" | tee -a $errorLogFileecho "      用户名:SYS" | tee -a $errorLogFileecho "       日志:ActiveMQ${AMQPort}端口全部异常" | tee -a $errorLogFileecho "     解决方案:结束3台ActiveMQ${AMQPort}进程进行归档。" | tee -a $errorLogFileecho "       级别:ERROR" | tee -a $errorLogFileecho "     其他参数:" | tee -a $errorLogFileecho "end----------------------------------------------------" | tee -a $errorLogFilefor itemServer in $remote_hostsdoping -c2 -i0.3 -W1 $itemServer &>/dev/nullif [ $? -ne 0 ]; thenecho "${itemServer},无法ping通!" | tee -a $logfileelseecho "开始结束进程:${itemServer}:${AMQPort}:${AMQPath}" | tee -a $logfilestopresult=$(sshpass -p "${remote_host_right_password}" ssh -o StrictHostKeyChecking=no $remote_host_user@$itemServer "ps -ef |grep "$AMQPath" | grep -v grep| awk '{print \$2}'| xargs kill -9 >/dev/null 2>&1 &")echo "stopresult:${stopresult}" | tee -a $logfileamqwatchCheckResult=$(sshpass -p "${remote_host_right_password}" ssh -o StrictHostKeyChecking=no $remote_host_user@$itemServer "ps -ef |grep amqwatch.sh |grep -v grep |wc -l;")echo "amqwatchCheckResult:${amqwatchCheckResult}" | tee -a $logfileif [ $amqwatchCheckResult -ne 0 ]; thenecho "${itemServer}监控脚amqwatch.sh本正常!" | tee -a $logfile elseecho "${itemServer}监控脚本amqwatch.sh不正常!" | tee -a $logfileecho "确定脚本文件amqwatch.sh:${itemServer}:${AMQPort}:${AMQPath}" | tee -a $logfileamqwatchFileResult=$(sshpass -p "${remote_host_right_password}" ssh -o StrictHostKeyChecking=no $remote_host_user@$itemServer "[ -e ${amqwatchPathFile} ] && echo 1 || echo 0;")echo "amqwatchFileResult:${amqwatchFileResult}" | tee -a $logfileif [ $amqwatchFileResult = 1 ]; thenecho "远程启动amqwatch.sh:${itemServer}:${AMQPort}:${AMQPath}" | tee -a $logfileamqwatchRunResult=$(sshpass -p "${remote_host_right_password}" ssh -o StrictHostKeyChecking=no $remote_host_user@$itemServer "su - root -c '${amqwatchPathFile} &' >/dev/null 2>&1 &")echo "amqwatchRunResult:${amqwatchRunResult}" | tee -a $logfileelseecho "远程归档mv:${itemServer}:${AMQPort}:${AMQPath}" | tee -a $logfileamqMVDataResult=$(sshpass -p "${remote_host_right_password}" ssh -o StrictHostKeyChecking=no $remote_host_user@$itemServer "mv ${AMQPath}data ${AMQPath}data.bak${cur_datetime} &") echo "amqMVDataResult${amqMVDataResult}" | tee -a $logfileecho "远程启动./activemq start:${itemServer}:${AMQPort}:${AMQPath}" | tee -a $logfileamqStartResult=$(sshpass -p "${remote_host_right_password}" ssh -o StrictHostKeyChecking=no $remote_host_user@$itemServer "${AMQPath}bin/./activemq start >/dev/null 2>&1 &") echo "amqStartResult:${amqStartResult}" | tee -a $logfilefififi donefielseecho "请安装nact和sshpass!" | tee -a $logfilefiecho "检查${AMQPort}端口end" | tee -a $logfile
}while true; do#AMQ定期归档begincur_date="`date +%Y-%m-%d`";currTime=$(date +"%Y-%m-%d %T")cur_datetime="`date +%Y-%m-%d-%H-%M-%S`";#分cur_date_M="`date +%M`";#时cur_date_H="`date +%H`";#周cur_date_W="`date +%w`";#日志输出 echo "日志输出"| tee -a $logfilelogfile="${logPath}/${cur_date}.log" #归档开关 1-开,开启定时归档;0-关,不归档;if [ $data_keep_run = 1 ]; then#if [ $cur_date_H = "05" ]; then#凌晨5点执行if [ $cur_date_W = $data_keep_week ] && [ $cur_date_H = $data_keep_hour ]; then#每周日凌晨5点执行echo "${currTime}执行定时归档[周${data_keep_week},时${data_keep_hour}]![data_keep_state:${data_keep_state},data_keep_61616_state:${data_keep_61616_state},data_keep_61626_state:${data_keep_61626_state}]" | tee -a $logfileif [ $data_keep_state = 0 ]; then#归档状态进行中data_keep_state=1;#确认是否有待消费MQ消息beginecho "开始确认是否有待消费(Number Of Pending Messages)MQ消息![data_keep_state:${data_keep_state},data_keep_61616_state:${data_keep_61616_state},data_keep_61626_state:${data_keep_61626_state}]" | tee -a $logfilecur_curl_datetime="`date +%Y-%m-%d-%H-%M-%S`";#未消费消息检查结果0-下载队列xml文件错误,1-没有未消费队列或者只有死信队列,可执行归档,2-有未消费队列,不执行归档check61616PendingMessagesResult=0;activemq61616PathXml="${logPath}/activemq61616-${cur_curl_datetime}.xml";activemq61616PathUrl="http://${check61616ServerIP}:8161/admin/xml/queues.jsp"#curl -u admin:admin -o activemq61616-data.xml "http://172.26.153.110:8161/admin/xml/queues.jsp"curl -u $data_keep_xml_user:$data_keep_xml_password -o $activemq61616PathXml $activemq61616PathUrl#确认下载61616队列xml文件格式正常curl61616Result=`grep -E '<queues>|<queue name=' $activemq61616PathXml |wc -l`echo "curl61616Result:$curl61616Result" | tee -a $logfileif [ $curl61616Result = 0 ]; thenecho "下载61616队列xml文件错误${activemq61616PathUrl},无法确认未消费队列[curl61616Result:$curl61616Result],此次定时归档失败!" | tee -a $logfileecho "start-----------------------------------------------------"  | tee -a $errorLogFileecho "     日志编号:监控脚本-2001" | tee -a $errorLogFileecho "       时间:$currTime" | tee -a $errorLogFileecho "     主机名称:$local_host($local_ip)" | tee -a $errorLogFileecho "       步骤:0" | tee -a $errorLogFileecho "        类:ActiveMQ" | tee -a $errorLogFileecho "     功能描述:定时归档[周${data_keep_week},时${data_keep_hour}]" | tee -a $errorLogFileecho "      用户名:SYS" | tee -a $errorLogFileecho "       日志:下载61616队列xml文件错误${activemq61616PathUrl},无法确认未消费队列[curl61616Result:$curl61616Result],此次定时归档失败!" | tee -a $errorLogFileecho "     解决方案:确认ActiveMQ-8161web管理服务正常。" | tee -a $errorLogFileecho "       级别:ERROR" | tee -a $errorLogFileecho "     其他参数:activemq61616PathXml:${activemq61616PathXml},data_keep_xml_user:${data_keep_xml_user},data_keep_xml_password:${data_keep_xml_password}]" | tee -a $errorLogFileecho "end----------------------------------------------------" | tee -a $errorLogFileelseecho "下载61616队列xml文件正常${activemq61616PathUrl},[curl61616Result:$curl61616Result]" | tee -a $logfile#统计61616未消费队列#grep -E --color 'size="[1-9][0-9]*"' activemq61616-data.xmlActiveMQ61616_Pending_Num=`grep -E --color 'size="[1-9][0-9]*"' $activemq61616PathXml |wc -l`echo "统计61616未消费队列[ActiveMQ61616_Pending_Num:$ActiveMQ61616_Pending_Num]" | tee -a $logfile#统计61616死信队列ActiveMQ61616_DLQ_Num=`grep -C 2 -E --color '<queue name="ActiveMQ.DLQ">' $activemq61616PathXml |grep  -E --color 'size="[1-9][0-9]*"' |wc -l`echo "统计61616死信队列[ActiveMQ61616_DLQ_Num:$ActiveMQ61616_DLQ_Num]" | tee -a $logfileif [ $ActiveMQ61616_Pending_Num = 0 ] || [ $ActiveMQ61616_Pending_Num = $ActiveMQ61616_DLQ_Num ]; then#没有未消费队列或者只有死信队列,执行61616归档check61616PendingMessagesResult=1;else#有未消费队列,无法执行61616归档,输出告警check61616PendingMessagesResult=2;fifiecho "完成确认61616是否有待消费(Number Of Pending Messages)MQ消息![data_keep_state:${data_keep_state},data_keep_61616_state:${data_keep_61616_state},data_keep_61626_state:${data_keep_61626_state}][check61616PendingMessagesResult:$check61616PendingMessagesResult]" | tee -a $logfile#未消费消息检查结果0-下载队列xml文件错误,1-没有未消费队列或者只有死信队列,可执行归档,2-有未消费队列,不执行归档check61626PendingMessagesResult=0;activemq61626PathXml="${logPath}/activemq61626-${cur_curl_datetime}.xml";activemq61626PathUrl="http://${check61626ServerIP}:8162/admin/xml/queues.jsp"curl -u $data_keep_xml_user:$data_keep_xml_password -o $activemq61626PathXml $activemq61626PathUrl#确认下载61626队列xml文件格式正常curl61626Result=`grep -E '<queues>|<queue name=' $activemq61626PathXml |wc -l`echo "curl61626Result:$curl61626Result" | tee -a $logfileif [ $curl61626Result = 0 ]; thenecho "下载61626队列xml文件错误${$activemq61626PathUrl},无法确认未消费队列[curl61626Result:$curl61626Result],此次定时归档失败!" | tee -a $logfileecho "start-----------------------------------------------------"  | tee -a $errorLogFileecho "     日志编号:监控脚本-2001" | tee -a $errorLogFileecho "       时间:$currTime" | tee -a $errorLogFileecho "     主机名称:$local_host($local_ip)" | tee -a $errorLogFileecho "       步骤:0" | tee -a $errorLogFileecho "        类:ActiveMQ" | tee -a $errorLogFileecho "     功能描述:定时归档[周${data_keep_week},时${data_keep_hour}]" | tee -a $errorLogFileecho "      用户名:SYS" | tee -a $errorLogFileecho "       日志:下载61626队列xml文件错误${activemq61626PathUrl},无法确认未消费队列[curl61626Result:$curl61626Result],此次定时归档失败!" | tee -a $errorLogFileecho "     解决方案:确认ActiveMQ-8162web管理服务正常。" | tee -a $errorLogFileecho "       级别:ERROR" | tee -a $errorLogFileecho "     其他参数:activemq61626PathXml:${activemq61626PathXml},data_keep_xml_user:${data_keep_xml_user},data_keep_xml_password:${data_keep_xml_password}]" | tee -a $errorLogFileecho "end----------------------------------------------------" | tee -a $errorLogFileelseecho "下载61626队列xml文件正常${activemq61626PathUrl},[curl61626Result:$curl61626Result]" | tee -a $logfile#统计61626未消费队列#grep -E --color 'size="[1-9][0-9]*"' activemq61626-data.xmlActiveMQ61626_Pending_Num=`grep -E --color 'size="[1-9][0-9]*"' $activemq61626PathXml |wc -l`echo "统计61626未消费队列[ActiveMQ61626_Pending_Num:$ActiveMQ61626_Pending_Num]" | tee -a $logfile#统计61626死信队列ActiveMQ61626_DLQ_Num=`grep -C 2 -E --color '<queue name="ActiveMQ.DLQ">' $activemq61626PathXml |grep  -E --color 'size="[1-9][0-9]*"' |wc -l`echo "统计61626死信队列[ActiveMQ61626_DLQ_Num:$ActiveMQ61626_DLQ_Num]" | tee -a $logfileif [ $ActiveMQ61626_Pending_Num = 0 ] || [ $ActiveMQ61626_Pending_Num = $ActiveMQ61626_DLQ_Num ]; then#没有未消费队列或者只有死信队列,执行61626归档check61626PendingMessagesResult=1;else#有未消费队列,无法执行61626归档,输出告警check61626PendingMessagesResult=2;fifiecho "完成确认61626是否有待消费(Number Of Pending Messages)MQ消息![data_keep_state:${data_keep_state},data_keep_61616_state:${data_keep_61616_state},data_keep_61626_state:${data_keep_61626_state}][check61626PendingMessagesResult:$check61626PendingMessagesResult]" | tee -a $logfile#确认是否有待消费MQ消息end#记录本次执行归档结果data_keep_61616_state_now=$data_keep_61616_state;data_keep_61626_state_now=$data_keep_61626_state;for itemServer in $remote_hostsdoping -c2 -i0.3 -W1 $itemServer &>/dev/nullif [ $? -ne 0 ]; thenecho "${itemServer},无法ping通!" | tee -a $logfileelseecho "开始执行归档和清理begin" | tee -a $logfileif [ $data_keep_61616_state -ne 1 ]; thenecho "开始结束进程:${itemServer}:${P1}" | tee -a $logfilelastDateTime=`date -d "${data_keep_61616_last_date}" +%s`;nowDate=$(date +"%Y-%m-%d %T");nowDateTime=`date -d "${nowDate}" +%s`;CountSeconds=$(($nowDateTime-$lastDateTime));CountDays=0;if [ $CountSeconds -gt 86400 ]; thenCountDays=`expr $CountSeconds / 86400`;fiecho "61616距离上次归档天数:[CountSeconds:${CountSeconds},CountDays:${CountDays}]" | tee -a $logfile#可执行归档或者离上次成功归档超过1个月(30天)if [ $check61616PendingMessagesResult = 1 ] || [ $CountDays -ge $data_keep_day_count ]; thenstopresult=$(sshpass -p "${remote_host_right_password}" ssh -o StrictHostKeyChecking=no $remote_host_user@$itemServer "ps -ef |grep "$P1" | grep -v grep| awk '{print \$2}'| xargs kill -9 >/dev/null 2>&1 &")data_keep_61616_last_date=$(date +"%Y-%m-%d %T")data_keep_61616_state_now=1;echo "${data_keep_61616_last_date}完成结束进程!stopresult:${stopresult}" | tee -a $logfileelsedata_keep_61616_state_now=0;echo "未执行结束进程,8161有待消费MQ消息或者下载数据异常:${itemServer}:${P1}" | tee -a $logfilefielseecho "61616今天归档成功,不需要重复归档![data_keep_state:${data_keep_state},data_keep_61616_state:${data_keep_61616_state},data_keep_61626_state:${data_keep_61626_state}]" | tee -a $logfilefiif [ $data_keep_61626_state -ne 1 ]; thenecho "开始结束进程:${itemServer}:${P2}" | tee -a $logfilelastDateTime=`date -d "${data_keep_61626_last_date}" +%s`;nowDate=$(date +"%Y-%m-%d %T");nowDateTime=`date -d "${nowDate}" +%s`;CountSeconds=$(($nowDateTime-$lastDateTime));CountDays=0;if [ $CountSeconds -gt 86400 ]; thenCountDays=`expr $CountSeconds / 86400`;fiecho "61626距离上次归档天数:[CountSeconds:${CountSeconds},CountDays:${CountDays}]" | tee -a $logfile#可执行归档或者离上次成功归档超过1个月(30天)if [ $check61626PendingMessagesResult = 1 ] || [ $CountDays -ge $data_keep_day_count ]; thenstopresult2=$(sshpass -p "${remote_host_right_password}" ssh -o StrictHostKeyChecking=no $remote_host_user@$itemServer "ps -ef |grep "$P2" | grep -v grep| awk '{print \$2}'| xargs kill -9 >/dev/null 2>&1 &")data_keep_61626_last_date=$(date +"%Y-%m-%d %T");data_keep_61626_state_now=1;echo "${data_keep_61626_last_date}完成结束进程!stopresult2:${stopresult2}" | tee -a $logfileelsedata_keep_61626_state_now=0;echo "未执行结束进程,8162有待消费MQ消息或者下载数据异常:${itemServer}:${P2}" | tee -a $logfilefielseecho "61626今天归档成功,不需要重复归档![data_keep_state:${data_keep_state},data_keep_61616_state:${data_keep_61616_state},data_keep_61626_state:${data_keep_61626_state}]" | tee -a $logfilefiif [ $data_keep_61616_state -ne 1 ]; thenecho "开始清理:${itemServer}:${P1}" | tee -a $logfile#find /mpjava/activemq-cluster1/ -mtime +7 -type d -name "data.bak*" -exec rm -rf {} \;rmresult=$(sshpass -p "${remote_host_right_password}" ssh -o StrictHostKeyChecking=no $remote_host_user@$itemServer "find "$P1" -mtime +7 -type d -name 'data.bak*' -exec rm -rf {} \;")echo "rmresult:${rmresult}" | tee -a $logfileelseecho "61616今天清理成功,不需要再清理![data_keep_state:${data_keep_state},data_keep_61616_state:${data_keep_61616_state},data_keep_61626_state:${data_keep_61626_state}]" | tee -a $logfilefiif [ $data_keep_61626_state -ne 1 ]; thenecho "开始清理:${itemServer}:${P2}" | tee -a $logfile#find /mpjava/activemq-cluster2/ -mtime +7 -type d -name "data.bak*" -exec rm -rf {} \;rmresult2=$(sshpass -p "${remote_host_right_password}" ssh -o StrictHostKeyChecking=no $remote_host_user@$itemServer "find "$P2" -mtime +7 -type d -name 'data.bak*' -exec rm -rf {} \;")echo "rmresult2:${rmresult2}" | tee -a $logfileelseecho "61626今天清理成功,不需要再清理![data_keep_state:${data_keep_state},data_keep_61616_state:${data_keep_61616_state},data_keep_61626_state:${data_keep_61626_state}]" | tee -a $logfilefiecho "完成执行归档和清理end" | tee -a $logfilefi done#更新本次执行归档结果data_keep_61616_state=$data_keep_61616_state_now;data_keep_61626_state=$data_keep_61626_state_now;#清理7天前/mpjava/amqportwath/*.log和*.xml文件echo "清理7天前${logPath}*.log和*.xml文件" | tee -a $logfilefind ${logPath} -mtime +7 -type f -name "*.log" -exec rm -rf {} \;find ${logPath} -mtime +7 -type f -name "*.xml" -exec rm -rf {} \;#如果61616或者61626归档失败,10分钟后重试if [ $data_keep_61616_state -ne 1 ] || [ $data_keep_61626_state -ne 1 ]; thendata_keep_state=0;#if [ $data_keep_state = 1 ]; then if [ $data_keep_61616_state -ne 1 ]; then #61616归档失败echo "61616归档失败!" | tee -a $logfileecho "start-----------------------------------------------------"  | tee -a $errorLogFileecho "     日志编号:监控脚本-2001" | tee -a $errorLogFileecho "       时间:$currTime" | tee -a $errorLogFileecho "     主机名称:$local_host($local_ip)" | tee -a $errorLogFileecho "       步骤:0" | tee -a $errorLogFileecho "        类:ActiveMQ" | tee -a $errorLogFileecho "     功能描述:定时归档[周${data_keep_week},时${data_keep_hour}]" | tee -a $errorLogFileecho "      用户名:SYS" | tee -a $errorLogFileecho "       日志:61616归档失败!原因是有待消费MQ消息或者下载数据异常。" | tee -a $errorLogFileecho "     解决方案:非生产时间,手动执行归档(结束三台MQ服务器的6个activemq进程)。" | tee -a $errorLogFileecho "       级别:ERROR" | tee -a $errorLogFileecho "     其他参数:" | tee -a $errorLogFileecho "end----------------------------------------------------" | tee -a $errorLogFilefiif [ $data_keep_61626_state -ne 1 ]; then #61626归档失败echo "61626归档失败!" | tee -a $logfileecho "start-----------------------------------------------------"  | tee -a $errorLogFileecho "     日志编号:监控脚本-2001" | tee -a $errorLogFileecho "       时间:$currTime" | tee -a $errorLogFileecho "     主机名称:$local_host($local_ip)" | tee -a $errorLogFileecho "       步骤:0" | tee -a $errorLogFileecho "        类:ActiveMQ" | tee -a $errorLogFileecho "     功能描述:定时归档[周${data_keep_week},时${data_keep_hour}]" | tee -a $errorLogFileecho "      用户名:SYS" | tee -a $errorLogFileecho "       日志:61626归档失败!原因是有待消费MQ消息或者下载数据异常。" | tee -a $errorLogFileecho "     解决方案:非生产时间,手动执行归档(结束三台MQ服务器的6个activemq进程)。" | tee -a $errorLogFileecho "       级别:ERROR" | tee -a $errorLogFileecho "     其他参数:" | tee -a $errorLogFileecho "end----------------------------------------------------" | tee -a $errorLogFilefi#fiecho "61616或者61626归档失败,10分钟后重试。[data_keep_state:${data_keep_state},data_keep_61616_state:${data_keep_61616_state},data_keep_61626_state:${data_keep_61626_state}]" | tee -a $logfileecho "sleep:10分钟(600s)" | tee -a $logfilesleep 600fielseecho "${currTime}今天已完成归档![周${data_keep_week},时${data_keep_hour}][data_keep_state:${data_keep_state},data_keep_61616_state:${data_keep_61616_state},data_keep_61626_state:${data_keep_61626_state}]" | tee -a $logfileecho "sleep:10分钟(600s)" | tee -a $logfilesleep 600fielseecho "${currTime}非归档时间![周${data_keep_week},时${data_keep_hour}][data_keep_state:${data_keep_state},data_keep_61616_state:${data_keep_61616_state},data_keep_61626_state:${data_keep_61626_state}]" | tee -a $logfile#归档状态复原data_keep_61616_state=0;data_keep_61626_state=0;data_keep_state=0;echo "${currTime}归档状态复原![data_keep_state:${data_keep_state},data_keep_61616_state:${data_keep_61616_state},data_keep_61626_state:${data_keep_61626_state}]" | tee -a $logfilefifi#AMQ定期归档end if [ $data_keep_state = 0 ]; then #AMQ端口61616/61626检查begincheck61616PortReslut=0check61616ServerIP=""checkAMQPort 61616 $P1check61616PortReslut=$checkPortReslutcheck61616ServerIP=$checkPortServerIPecho "check61616PortReslut${check61616PortReslut}" | tee -a $logfileecho "check61616ServerIP${check61616ServerIP}" | tee -a $logfilecheck61626PortReslut=0check61626ServerIP=""checkAMQPort 61626 $P2check61626PortReslut=$checkPortReslutcheck61626ServerIP=$checkPortServerIPecho "check61626PortReslut:${check61626PortReslut}" | tee -a $logfileecho "check61626ServerIP${check61626ServerIP}" | tee -a $logfile#AMQ端口61616/61626检查end if [ $check61616PortReslut -ne 0 ] && [ $check61626PortReslut -ne 0 ]; then#检查端口正常,每次循环沉睡1分钟(60s)echo "sleep:1分钟(60s)" | tee -a $logfilesleep 60else#检查端口不正常,结束进程后,20分钟再进行确认echo "sleep:20分钟(1200s)" | tee -a $logfilesleep 1200fifi
done

注意事项

  1. 防火墙配置
    防火墙需开放以下端口:

    • 4369 (epmd)
    • 5672-5673 (AMQP)
    • 15672 (HTTP API)
    • 25672 (Erlang分发)
  2. TLS加密
    建议在生产环境中使用TLS加密通信。可以使用以下命令生成证书:

    openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
    
  3. 定期清理策略
    设置队列的自动清理策略:

    rabbitmqctl set_policy auto-expire "^log.*" '{"expires":1800000}' --apply-to queues
    

完整部署包及配置文件获取

可以通过以下链接下载RabbitMQ的完整部署包及配置文件:

wget https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.12.2/rabbitmq-server-generic-unix-3.12.2.tar.xz

通过以上步骤,您可以快速搭建一个高可用的RabbitMQ集群。希望本文对您有所帮助!如果有任何问题,欢迎在评论区留言。

相关文章:

RabbitMQ 3.12.2:单节点与集群部署实战指南

前言&#xff1a;在当今的分布式系统架构中&#xff0c;消息队列已经成为不可或缺的组件之一。它不仅能够实现服务之间的解耦&#xff0c;还能有效提升系统的可扩展性和可靠性。RabbitMQ 作为一款功能强大且广泛使用的开源消息中间件&#xff0c;凭借其高可用性、灵活的路由策略…...

Node.js技术原理分析系列——如何在Node.js中新增一个内置模块

本文由体验技术团队曹杨毅原创。 Node.js 是一个开源的、跨平台的JavaScript运行时环境&#xff0c;它允许开发者在服务器端运行JavaScript代码。Node.js 是基于Chrome V8引擎构建的&#xff0c;专为高性能、高并发的网络应用而设计&#xff0c;广泛应用于构建服务器端应用程序…...

从低清到4K的魔法:FlashVideo突破高分辨率视频生成计算瓶颈(港大港中文字节)

论文链接&#xff1a;https://arxiv.org/pdf/2502.05179 项目链接&#xff1a;https://github.com/FoundationVision/FlashVideo 亮点直击 提出了 FlashVideo&#xff0c;一种将视频生成解耦为两个目标的方法&#xff1a;提示匹配度和视觉质量。通过在两个阶段分别调整模型规模…...

康耐视CAM-CIC-10MR-10-GC工业相机

康耐视(COGNEX)的工业相机CAM-CIC-10MR-10-GC是CAM-CIC-10MR系列中的一款型号,主要应用于工业自动化检测和高精度视觉系统 基本参数与特性 分辨率与帧率: CAM-CIC-10MR-10-GC属于康耐视CIC系列,具备10MP(1000万像素)的分辨能力,帧率为10fps。该系列相机支持卷帘快门(R…...

解惑Python:一文解决osgeo库安装失败问题

Osgeo&#xff08;Open Source Geospatial Foundation&#xff09;是一个支持开源地理空间数据处理的基金会&#xff0c;我们可以在python中使用“osgeo”库来访问其提供的高效地理空间数据。例如&#xff0c;我们使用该模块提供的GDAL处理栅格数据&#xff0c;使用OGR处理矢量…...

3、树莓派5 安装VNC查看器 开启VNC服务器

在前序文章中&#xff08; 2、树莓派5第一次开机&#xff09;&#xff0c;可以使用三种方式开机&#xff0c;其中使用网线及wifi的方式均需要使用到VNC查看器进行远程桌面控制&#xff0c;本文将介绍如何下载安装并配置及使用VNC查看器及服务器&#xff0c;对前序文章做一些补充…...

Django 创建表时 “__str__ ”方法的使用

在 Django 模型中&#xff0c;__str__ 方法是一个 Python 特殊方法&#xff08;也称为“魔术方法”&#xff09;&#xff0c;用于定义对象的字符串表示形式。它的作用是控制当对象被转换为字符串时&#xff0c;应该返回什么样的内容。 示例&#xff1a; 我在初学ModelForm时尝…...

STM32 CAN过滤器配置和应用方法介绍

目录 概述 一、CAN过滤器核心概念 二、过滤器配置步骤&#xff08;以标准ID为例&#xff09; 三、不同模式的配置示例 四、高级配置技巧 五、调试与问题排查 六、关键计算公式 总结 概述 在STM32微控制器中&#xff0c;CAN过滤器可以配置为标识符屏蔽模式和标识符列表模…...

【第1章:深度学习概览——1.3 深度学习的核心组件与概念解析之神经网络基础】

大家好!今天咱们一头扎进深度学习的神秘领域,好好探索一下其最重要的基石 —— 神经网络。不管你是深度学习的新手小白,还是已经接触过一些基础概念,这篇文章都能助力你更透彻地理解神经网络的原理和运作机制。咱们从最基础的知识入手,一步步揭开神经网络的神秘面纱! 一、…...

Python中如何进行数据库连接?

在 Python 中进行数据库连接&#xff0c;不同的数据库需要使用不同的库。下面分别介绍几种常见数据库&#xff08;SQLite、MySQL、PostgreSQL&#xff09;的连接方法。 1. 连接 SQLite 数据库 SQLite 是一种轻量级的嵌入式数据库&#xff0c;Python 标准库中自带了sqlite3模块…...

解析 WebGPU 中 device.createBuffer 的参数意义

在 WebGPU 开发里&#xff0c;device.createBuffer 方法扮演着至关重要的角色&#xff0c;它用于创建一个 GPU 缓冲区对象&#xff0c;这个对象能够存储顶点数据、索引数据、统一数据等。下面我们就来详细剖析该方法各个参数的意义。 1. size&#xff1a;决定缓冲区容量 size …...

PLC的集成RAM,存储器卡,用户程序存储空间,数据存储容量分别指的什么,有什么关联?

1. 集成RAM 定义&#xff1a;集成RAM&#xff08;随机存取存储器&#xff09;是PLC内部的高速易失性存储器&#xff0c;用于临时存储运行时的数据&#xff08;如输入/输出状态、中间变量、计数器/定时器的当前值等&#xff09;。 特点&#xff1a; 易失性&#xff1a;断电后数…...

BFS-FloodFill 算法 解决最短路问题 多源 解决拓扑排序

文章目录 一、FloodFill 算法[733. 图像渲染](https://leetcode.cn/problems/flood-fill/description/)2.思路3.代码 [200. 岛屿数量](https://leetcode.cn/problems/number-of-islands/description/)2.思路3.代码 [LCR 105. 岛屿的最大面积](https://leetcode.cn/problems/ZL6…...

USB2.03.0接口区分usb top工具使用

一. USB2.0 & 3.0接口支持区分 1.1. 颜色判断 USB接口的颜色并不是判断版本的可靠标准&#xff0c;但根据行业常见规范分析如下&#xff1a; USB接口颜色与版本对照表&#xff1a; 接口颜色常见版本内部触点数量传输速度黑色USB2.04触点480 Mbps (60 MB/s)白色USB2.0(多…...

2025百度快排技术分析:模拟点击与发包算法的背后原理

一晃做SEO已经15年了&#xff0c;2025年还有人问我如何做百度快速排名&#xff0c;我能给出的答案就是&#xff1a;做好内容的前提下&#xff0c;多刷刷吧&#xff01;百度的SEO排名算法一直是众多SEO从业者研究的重点&#xff0c;模拟算法、点击算法和发包算法是百度快速排名的…...

idea 2019.3常用插件

idea 2019.3常用插件 文档 idea 2019.3常用插件idea 2023.3.7常用插件 idea 2019.3常用插件 插件名称插件版本说明1AceJump3.5.9AceJump允许您快速将插入符号导航到编辑器中可见的任何位置。只需按“ctrl&#xff1b;”&#xff0c;键入一个字符&#xff0c;然后在Ace Jump…...

【Python 学习 / 5】函数详解(定义、参数、作用域、lambda、内置函数)

文章目录 一、函数1. 定义函数1.1 基本函数定义1.2 带参数的函数1.3 带返回值的函数 2. 参数传递2.1 位置参数2.2 默认参数2.3 可变参数2.3.1 使用*args2.3.2 使用**kwargs 2.4 参数的混合使用 3. 作用域3.1 局部和全局变量3.2 global 关键字输出&#xff1a; 3.3 nonlocal关键…...

WPF7-数据绑定基础

1. WPF数据绑定试验 1.1. 数据绑定的核心实现1.2. {Binding}语法1.3. 理解 DataContext 1. WPF数据绑定试验 以下是一个简单的 WPF 数据绑定示例&#xff0c;使用两个TextBox控件分别表示Name和Age来进行进行数据绑定试验。 数据模型类 创建一个 Person 类&#xff0c;包含…...

http 与 https 的区别?

HTTP(超文本传输协议)和 HTTPS(安全超文本传输协议)是互联网通信的基础协议。随着网络技术的发展和安全需求的提升,HTTPS变得越来越重要。本文将深入探讨HTTP与HTTPS之间的区别,包括其工作原理、安全性、性能、应用场景及未来发展等。 1. HTTP与HTTPS的基本概念 1.1 HT…...

大数据学习(49) - Flink按键分区状态(Keyed State)

&&大数据学习&& &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 承认自己的无知&#xff0c;乃是开启智慧的大门 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一下博主哦&#x1f91…...

IP 路由基础 | 路由条目生成 / 路由表内信息获取

注&#xff1a;本文为 “IP 路由” 相关文章合辑。 未整理去重。 IP 路由基础 秦同学学学已于 2022-04-09 18:44:20 修改 一. IP 路由产生背景 我们都知道 IP 地址可以标识网络中的一个节点&#xff0c;并且每个 IP 地址都有自己的网段&#xff0c;各个网段并不相同&#xf…...

COBOL语言的移动应用开发

COBOL语言的移动应用开发探讨 引言 在信息技术快速发展的今天&#xff0c;移动应用开发已成为各行各业不可或缺的一部分。许多企业和开发者纷纷转向使用新兴的编程语言和开发工具&#xff0c;以满足不断变化的用户需求。然而&#xff0c;作为一种历史悠久的编程语言&#xff…...

TCP协议(Transmission Control Protocol)

TCP协议&#xff0c;即传输控制协议&#xff0c;其最大的特征就是对传输的数据进行可靠、高效的控制&#xff0c;其段格式如下&#xff1a; 源端口和目的端口号表示数据从哪个进程来&#xff0c;到哪个进程去&#xff0c;四位报头长度表示的是TCP头部有多少个4字节&#xff0c;…...

C语言数组之二维数组

C语言 主要内容 数组 二维数组 数组 二维数组 定义 二维数组本质上是一个行列式的组合&#xff0c;也就是说二维数组由行和列两部分组成&#xff0c;属于多维数组。二维数组数据是通过行列进行解读。二维数组可被视为一个特殊的一维数组&#xff0c;相当于二维数组又是一…...

计算机专业知识【软件开发中的常用图表:E - R图、HIPO、DFD、N - S、PAD详解】

在软件开发过程中&#xff0c;有许多种图表工具被用于不同阶段的设计和分析&#xff0c;帮助开发者更清晰地理解系统结构、数据流程和算法逻辑。下面将详细介绍E - R图、HIPO图、DFD图、N - S图和PAD图&#xff0c;包括它们的样子和用途。 一、E - R图&#xff08;实体 - 联系…...

多人协同开发 —— Git Aoneflow工作流

一、Aoneflow工作流核心架构 #mermaid-svg-rwTOe9qYwzG3wkdy {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-rwTOe9qYwzG3wkdy .error-icon{fill:#552222;}#mermaid-svg-rwTOe9qYwzG3wkdy .error-text{fill:#552222…...

VSCode运行Go程序报错:Unable to process `evaluate`: debuggee is running

如果使用默认的VSCode的服务器来运行Go程序&#xff0c;那么使用fmt.Scan函数输入数据的时候就会报错&#xff0c;我们需要修改launch.json文件&#xff0c;将Go程序运行在shell终端上。 main.go package mainimport "fmt"func main() {var n intfmt.Scan(&n)v…...

Mybatis高级(动态SQL)

目录 一、动态SQL 1.1 数据准备&#xff1a; 1.2 <if>标签 1.3<trim> 标签 1.4<where>标签 1.5<set>标签 1.6 <foreach>标签 1.7<include> 标签 一、动态SQL 动态SQL是Mybatis的强⼤特性之⼀&#xff0c;能够完成不同条件下不同…...

在 Vue 3 中使用 Lottie 动画:实现一个加载动画

在现代前端开发中&#xff0c;动画是提升用户体验的重要元素之一。Lottie 是一个流行的动画库&#xff0c;它允许我们使用 JSON 文件来渲染高质量的动画。本文将介绍如何在 Vue 3 项目中集成 Lottie 动画&#xff0c;并实现一个加载动画效果。 如果对你有帮助请帮忙点个&#x…...

建筑行业安全技能竞赛流程方案

一、比赛时间&#xff1a; 6月23日8&#xff1a;30分准时到场&#xff1b;9&#xff1a;00&#xff0d;10&#xff1a;00理论考试&#xff1b;10&#xff1a;10-12:00现场隐患答疑&#xff1b;12:00-13&#xff1a;30午餐&#xff1b;下午13&#xff1a;30-15&#xff1a;30现场…...

Mybatisplus自定义sql

文章目录 引言流程 引言 mybatisplus最擅长的将where里面的语句给简便化&#xff0c;而不用我们自己写标签来实现条件查询 但是很多公司规范我们将sql写在mapper层中&#xff0c;不能写在service中 而且一些语句查询的不同select count(*) xxx from xxx 也难以用mp来实现 如何…...

情书网源码 情书大全帝国cms7.5模板

源码介绍 帝国cms7.5仿《情书网》模板源码&#xff0c;同步生成带手机站带采集。适合改改做文学类的网站。 效果预览 源码获取 情书网源码 情书大全帝国cms7.5模板...

基于Unity引擎的网络通信架构深度解析——以NetworkConnectionController为例

一、架构概览与设计理念 本文将以重构后的NetworkConnectionController为核心&#xff0c;深入分析基于Unity引擎的MMO网络通信架构设计。该模块采用分层设计思想&#xff0c;通过连接池管理、流量控制、心跳监测等多维度技术手段&#xff0c;构建了一个高性能、可扩展的网络通…...

C#学习之DataGridView控件

目录 一、DataGridView控件常用属性、方法、事件汇总表 1. 常用方法、属性和事件汇总 二、DataGridView 控件的常用方法调用 1. DataBind() 方法 2. Clear() 方法 3. Refresh() 方法 4. Sort() 方法 5. ClearSelection() 方法 6. BeginEdit() 方法 7. EndEdit() 方法…...

midjourney 一 prompt 提示词

midjourney 不需要自然语言的描述&#xff0c;它只需要关键词即可。 一个完整的Midjourney prompt通常包括三个部分 图片提示&#xff08;Image Prompts&#xff09;、文本提示&#xff08;Text Prompt&#xff09;和参数&#xff08;Parameters&#xff09;。 1、图片提示(…...

谈谈 wait 和 notify

目录 1 wait()方法 2 notify()⽅法 3 wait 和 sleep 的区别 多线程调度是随机的, 很多时候希望多个线程能够按照咱们规定的顺序来执行. 完成线程之间的配合工作. wait和notify就是一个用来协调线程顺序的重要工具. 这俩方法都是 Object 提供的方法. 随便找个对象&#xff0…...

250214-java类集框架

引言 类集框架本质上相当于是容器&#xff0c;容器装什么东西由程序员指定 1.单列集合 单列集合是list和set&#xff0c;list的实现类有ArrayList和LinkedList&#xff0c;前者是数组实现&#xff0c;后者是链表实现。list和set&#xff0c;前者有序、可重复&#xff0c;后者…...

Python学习心得异常处理

有些代码在操作的过程当中&#xff0c;如果不注意其所限定的条件&#xff0c;可能在输入函数值时引发一些程序的报错&#xff0c;这样为了让代码自己能做到抛除异常操作的情况&#xff0c;就得让代码具有排除异常的能力。下面的一些操作就使得代码具有该功能&#xff0c;处理异…...

【机器学习】线性回归 多项式线性回归

【机器学习系列】 KNN算法 KNN算法原理简介及要点 特征归一化的重要性及方式线性回归算法 线性回归与一元线性回归 线性回归模型的损失函数 多元线性回归 多项式线性回归 多项式线性回归 V1.0多项式回归多项式回归的公式 特征代换超越函数作为特征向量维度 V1.0 多项式回归 …...

链表和list

链表和list ‍ ​ ​ ​ ​ ​ ​ ​ ​ ​ 算法题中的经典操作&#xff1a;用空间代替时间​ ​ ​ ​ 双链表头插顺序&#xff1a; 1.先修改新结点的左右指针 2.然后修改结点y的左指针 3.最后修改哨兵位的右指针 双链表在任意位置&#xff08;p&#xff09;之后插入…...

vscode的一些实用操作

1. 焦点切换(比如主要用到使用快捷键在编辑区和终端区进行切换操作) 2. 跳转行号 使用ctrl g,然后输入指定的文件内容&#xff0c;即可跳转到相应位置。 使用ctrl p,然后输入指定的行号&#xff0c;回车即可跳转到相应行号位置。...

sass中@import升级@use的使用区别与案例

在 Sass 中&#xff0c;import 和 use 都用于模块化代码&#xff0c;但二者有显著区别。以下是主要差异和具体案例说明&#xff1a; 核心区别对比 特性 import (旧版) use (新版) 作用域 全局作用域&#xff08;变量/混合易冲突&#xff09; 局部作用域&#xff08;需通过…...

基于单片机ht7038 demo

单片机与ht7038 demo&#xff0c;三相电能表&#xff0c;电量数据包括电流电压功能&#xff0c;采用免校准方法 列表 ht7038模块/CORE/core_cm3.c , 17273 ht7038模块/CORE/core_cm3.h , 85714 ht7038模块/CORE/startup_stm32f10x_hd.s , 15503 ht7038模块/CORE/startup_stm32…...

基于YOLO11深度学习的胃肠道息肉智能检测分割与诊断系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标分割、人工智能

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…...

CViewState::InitializeColumns函数分析之_hdsaColumnStates的结构

CViewState::InitializeColumns函数分析之_hdsaColumnStates的结构 // Set up saved column state only if the saved state // contains information other than "nothing". if (_hdsaColumnStates) { UINT cStates DSA_GetItemCount(_hdsaColumnS…...

商淘云中英文外贸电商系统,助力传统企业杨帆出海

在全球经济一体化的浪潮下&#xff0c;传统企业纷纷渴望拓展海外市场&#xff0c;寻求新的增长机遇。然而&#xff0c;语言障碍、复杂的跨境交易流程、多元的支付体系以及迥异的消费习惯&#xff0c;如同重重壁垒&#xff0c;阻碍着传统企业扬帆出海的步伐。此时&#xff0c;商…...

--- Mysql事务 ---

什么是事务 因为事务的存在&#xff0c;可以使得多条sql语句一起执行&#xff0c;并且只有全部执行成功或全部执行失败俩种结果&#xff0c;保证了数据的安全&#xff0c;也使得这些sql语句拥有了原子性&#xff0c;隔离性&#xff0c;一致性&#xff0c;持久性&#xff08;AC…...

FreeRTOS第7篇:内存的“精打细算”——堆管理与内存分配

文/指尖动听知识库-星愿 文章为付费内容,商业行为,禁止私自转载及抄袭,违者必究!!! 文章专栏:深入FreeRTOS内核:从原理到实战的嵌入式开发指南 引言:嵌入式系统的“仓库管理员” 想象你是一家繁忙仓库的管理员:货物(内存块)需要被高效存取,货架(堆空间)必须避免…...

有效市场理论(Efficient Market Hypothesis,简称 EMH):市场真的“有效”吗?中英双语

有效市场理论&#xff08;EMH&#xff09;&#xff1a;市场真的“有效”吗&#xff1f; 1. 什么是有效市场理论&#xff1f; &#x1f4cc; 有效市场理论&#xff08;Efficient Market Hypothesis&#xff0c;简称 EMH&#xff09; 是由美国经济学家 尤金法玛&#xff08;Eug…...

STM32 HAL库USART串口中断编程:演示数据丢失

目录 一、开发环境 二、配置STM32CubeMX 三、代码实现与部署 四、运行结果&#xff1a; ​五、注意事项 上面讨论过,HAL_UART_Receive最容易丢数据了,可以考虑用中断来实现,但是HAL_UART_Receive_IT还不能直接用,容易数据丢失,实际工作中不会这样用,本文介绍STM32F103 HAL库函数…...