如何配置OpenShift命令式存活探针检测卡住的Oracle物化视图刷新服务
可以通过轮询日志匹配特定消息实现该检测,以下是具体实现方式、方案优劣以及更优的替代方案。
基于日志匹配的实现方式
前置要求
你的业务日志每行必须包含可被标准解析的时间戳(示例格式:2024-05-20 12:34:56 Refreshing materialized views),同时建议将业务日志落地到容器内的本地文件(比如/var/log/app.log),避免直接读取stdout日志的兼容性问题。如果日志配置了轮转,扫描时需要覆盖所有轮转后的日志文件。
检测脚本示例
将以下脚本存入容器镜像的/usr/local/bin/check_mv_stuck.sh,并添加可执行权限chmod +x /usr/local/bin/check_mv_stuck.sh:
#!/bin/bash # 配置参数 MAX_ALLOWED_HOURS=5 LOG_PATH="/var/log/app.log*" # 匹配所有轮转后的日志文件 # 时间转时间戳兼容函数 get_timestamp() { date -d "$1" +%s 2>/dev/null || date -jf "%Y-%m-%d %H:%M:%S" "$1" +%s 2>/dev/null } # 提取最后一次刷新开始、完成的时间 LAST_START=$(grep "Refreshing materialized views" $LOG_PATH | tail -n1 | awk '{print $1" "$2}') LAST_FINISH=$(grep "materialized view refreshed" $LOG_PATH | tail -n1 | awk '{print $1" "$2}') # 从未触发过刷新,返回正常 [ -z "$LAST_START" ] && exit 0 # 第一次触发刷新还未完成,计算运行时长 if [ -z "$LAST_FINISH" ]; then START_TS=$(get_timestamp "$LAST_START") [ $(( ($(date +%s) - START_TS) / 3600 )) -ge $MAX_ALLOWED_HOURS ] && exit 1 exit 0 fi START_TS=$(get_timestamp "$LAST_START") FINISH_TS=$(get_timestamp "$LAST_FINISH") # 上次刷新已完成,返回正常 [ $FINISH_TS -gt $START_TS ] && exit 0 # 当前正在刷新,计算运行时长 [ $(( ($(date +%s) - START_TS) / 3600 )) -ge $MAX_ALLOWED_HOURS ] && exit 1 exit 0
OpenShift存活探针配置
在Deployment/DeploymentConfig的spec.template.spec.containers下添加探针配置:
livenessProbe: exec: command: ["/bin/bash", "/usr/local/bin/check_mv_stuck.sh"] initialDelaySeconds: 60 # 服务启动后延迟60秒开始检测 periodSeconds: 300 # 每5分钟执行一次检测,无需过高频率 failureThreshold: 1 # 单次检测失败直接触发重启 timeoutSeconds: 10 # 检测脚本超时时间,避免检测本身卡住
方案优劣评估
- 优点:无需修改业务代码,仅通过新增脚本和探针配置即可实现,逻辑和业务卡住场景直接对应
- 缺点:强依赖日志格式和完整性,日志滚动、截断、格式变更都会导致检测失效;每次检测需要扫描日志文件,日志量大时会有额外资源消耗;如果程序在打印开始刷新的日志之前就卡住,会出现漏检
更推荐的最优实现方案
相比日志匹配,修改极少量业务代码维护状态标记的方案稳定性更高,实现也更简单:
- 业务代码改造:
- 打印
Refreshing materialized views的同时,在/tmp目录下创建mv_refresh.lock文件,写入当前时间戳 - 打印
materialized view refreshed的同时,删除mv_refresh.lock文件
- 打印
- 检测脚本逻辑:
#!/bin/bash MAX_ALLOWED_HOURS=5 LOCK_FILE="/tmp/mv_refresh.lock" # 锁文件不存在说明不在刷新阶段,返回正常 [ ! -f "$LOCK_FILE" ] && exit 0 # 计算刷新时长 START_TS=$(cat "$LOCK_FILE") [ $(( ($(date +%s) - START_TS) / 3600 )) -ge $MAX_ALLOWED_HOURS ] && exit 1 exit 0 - 探针配置和上述日志方案保持一致即可。
该方案的优势:不依赖日志系统,逻辑稳定无漏判误判风险;检测效率极高,不需要扫描大文件;实现成本极低,仅需要加几行业务代码。且/tmp目录默认是tmpfs,Pod重启后会自动清空,不会有残留文件导致误判。
内容的提问来源于stack exchange,提问作者Ketan_Gupta
相关产品推荐
相关产品推荐

