§0 前言
集群的高可用性可以直接简明的使用 SLA 来衡量,无所谓其他指标。
正常来讲,高可用对应了一整套方案,包括
- 预防:降低故障概率
- 发现:快速发现故障、甚至定位问题
- 恢复:快速恢复集群,这里只强调恢复集群可用性
说白了就是降低发病频率,然后早发现早治疗
预防
降低故障概率有两个主要方向
完善工作流程:包括制定研发红线、编码规范、测试规范、标准上线流程
比如,将灰度发布、线上验证、全量发布作为标准上线流程,将可灰度、可回滚、可观测作为必备指标可以极大降低新迭代的业务发生问题的概率并控制影响范围
完善异常场景处理:主要来源是对既发问题的复盘,以此为出发点推动补充不健全的业务、设计、实现方案、辅助工具
快速发现、定位问题
快速发现问题最直接的手段就是监控告警, 问题集中在监控数据的获取、存储、使用(统计分析)
快速定位问题主要依靠项目运行时的可见性/可观测性,这主要由日志或量化指标实现
快速恢复集群
这里有个误区:假设集群的不可用是因某因素导致的,那么快速恢复这个事只强调把集群恢复为可用状态,不强调排除此因素
这里的手段有很多,比如服务稳定性治理中的部分(熔断、降级、开关、隔离/舱闭),比如多地部署故障转移、故障驱逐,比如回滚、自动扩容等
§1 思路
本文中方案,就是快速恢复集群的一种方式,核心是始终保证集群中节点提供服务
其实正常的讲,更合理的思路应该是:始终保证集群中有足够的节点提供服务,即我需要一个至少 x 节点提供服务的集群
推荐使用更成熟健全的方案,比如上云、二开等直接增强集群能力的方式
但如果集群足够小且相对比较稳定时,可以采用此方案,成本基本为0
但需要注意:此方案会导致服务进程无脑重启,与故障驱逐相斥
§2 实现
以 nacos 集群为例,部署在 /data/nacos/
下
/etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=有效的邮箱或空着
# For details see man 4 crontabs
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
* * * * * root sh /data/pastor/pastor.sh
定时任务脚本
#!/bin/bash
source /etc/profile
### 进程关键词,用来搜索进程
PROCESS_KEY=nacos
### 日志文件夹路径
PATH_LOG="/data/pastor/log"
### 日志路径,记录脚本调用记录
PATH_2_SCHEDULE=""$PATH_LOG"/pastor.schedule.out"
### 日志路径,记录脚本执行记录
PATH_2_PASTOR=""$PATH_LOG"/pastor.$(date '+%Y%m%d').out"
### 唤起指令文件
CALLING_COMMAND="/data/pastor/pastor-calling-command.sh"
### 每次调用脚本,会有多次执行
### 间隔10秒,执行5次,留10秒给特殊情况
SLEEP_PERIOD_SECOND=10
REPEAT_TIMES=5
### 日志文件夹与文件检测,不存在时创建并记录 create 事件
if [ ! -d "$PATH_LOG" ];then
mkdir -p $PATH_LOG
touch $PATH_2_SCHEDULE
echo "[$( date '+%H%M%S' )] CREATE /log"
fi
if [ ! -e "$PATH_2_SCHEDULE" ];then
touch $PATH_2_SCHEDULE
echo "[$( date '+%H%M%S' )] CREATE" >> $PATH_2_SCHEDULE
fi
if [ ! -e "$PATH_2_PASTOR" ];then
touch $PATH_2_PASTOR
echo "[$( date '+%H%M%S' )] CREATE" >> $PATH_2_PASTOR
fi
### 记录脚本开始,正常应该成对出现,否则就是有问题
echo "[$( date '+%H%M%S')] START" >> $PATH_2_SCHEDULE
### 监听逻辑
### 为实现秒级监控,通过 REPEAT_TIMES & SLEEP_PERIOD_SECOND 控制
### 不记录重复信息,记录变更信息,记录唤起事件
for((i=0;i<REPEAT_TIMES;i++))
do
### 取上一条记录的 pid 与 当前用进程关键字找到的 pid
CURRENT_PID=$( ps -ef | grep $PROCESS_KEY | grep -v grep | awk '{print $2}' )
LAST_PID=$( tail -n 1 $PATH_2_PASTOR | awk '{print $2}' )
### echo "$LAST_PID <> $CURRENT_PID"
### 前后 pid 不一致时记录事件,否则忽略
if [ "$LAST_PID" != "$CURRENT_PID" ]
then
echo "[$( date '+%H%M%S' )] $CURRENT_PID" >> $PATH_2_PASTOR
fi
### 当前 pid 为空时,唤起进程
if [ -z "$CURRENT_PID" ]
then
sh ${CALLING_COMMAND}
echo "[$( date '+%H%M%S' )] PASTOR-HEALING " >> $PATH_2_PASTOR
fi
sleep $SLEEP_PERIOD_SECOND
done
### 记录脚本结束,正常应该成对出现,否则就是有问题
echo "[$(date '+%H%M%S')] END" >> $PATH_2_SCHEDULE
唤起脚本
echo "0000" >> /data/pastor/hhh
#nohup java -jar /data/pastor/demo-0.0.1-SNAPSHOT.jar > process.log 2>&1 &
sh /data/nacos/bin/startup.sh