Supervisor与Cron实现服务健康监控方案 1. 服务假死问题的本质与监控方案选型服务器进程假死是运维工作中最令人头疼的问题之一——进程仍在运行却不再响应请求。这种情况往往比彻底崩溃更难发现因为系统监控工具通常只能检测进程是否存在而无法判断其是否健康工作。假死现象通常由以下原因导致线程死锁或资源竞争未处理的异常阻塞主线程内存泄漏导致响应缓慢外部依赖服务超时未返回文件描述符耗尽我管理的一个Java Web服务就曾频繁出现假死进程存活但HTTP端口完全无响应。传统的进程监控工具如systemd对此束手无策这促使我研究出supervisorcron的组合方案。关键区别崩溃(crash)是进程退出假死(hang)是进程僵而不死。后者需要主动健康检查而非简单的进程存在性检查。2. Supervisor基础配置与进程管理Supervisor作为进程管理工具其核心优势在于提供守护进程功能崩溃后自动重启统一的进程状态管理接口详细的日志记录和事件通知典型配置示例/etc/supervisor/conf.d/webapp.conf[program:webapp] command/usr/bin/java -jar /opt/webapp/webapp.jar directory/opt/webapp userwebuser autostarttrue autorestarttrue startsecs10 startretries3 stderr_logfile/var/log/webapp.err.log stdout_logfile/var/log/webapp.out.log environmentJAVA_HOME/usr/lib/jvm/java-11-openjdk但默认配置只能处理进程崩溃场景。我们需要扩展其能力; 添加健康检查配置 killasgrouptrue stopasgrouptrue stopsignalINT stopwaitsecs603. 实现服务健康检查的Cron方案健康检查脚本是整套方案的核心。我推荐使用curl进行HTTP服务检查因为它支持连接超时和读取超时独立设置能处理HTTPS证书验证提供丰富的返回状态码健康检查脚本示例/opt/scripts/healthcheck.sh#!/bin/bash SERVICE_URLhttp://localhost:8080/health TIMEOUT5 RETRY3 for ((i1; i$RETRY; i)); do HTTP_CODE$(curl -s -o /dev/null -w %{http_code} --max-time $TIMEOUT $SERVICE_URL) if [ $HTTP_CODE -eq 200 ]; then exit 0 fi sleep 1 done # 所有重试失败后重启服务 supervisorctl restart webapp echo $(date) - Restarted webapp due to health check failure /var/log/service-monitor.log exit 1设置Cron任务crontab -e*/5 * * * * /opt/scripts/healthcheck.sh /dev/null 214. 高级监控策略与性能优化基础方案可以进一步优化多维度健康检查# 检查端口监听 ss -tulnp | grep :8080 || supervisorctl restart webapp # 检查线程状态Java应用 jstack $(pgrep -f webapp.jar) | grep -A10 main | grep RUNNABLE || supervisorctl restart webapp # 检查响应时间超过2秒视为异常 RESP_TIME$(curl -s -w %{time_total} -o /dev/null http://localhost:8080/health) [ $(echo $RESP_TIME 2 | bc) -eq 1 ] supervisorctl restart webapp资源占用控制; 在supervisor配置中添加资源限制 [program:webapp] ... priority500 process_name%(program_name)s_%(process_num)02d numprocs1 umask022日志轮转配置/etc/logrotate.d/webapp/var/log/webapp*.log { daily missingok rotate 30 compress delaycompress notifempty create 640 webuser adm sharedscripts postrotate /usr/bin/supervisorctl restart webapp /dev/null 21 || : endscript }5. 异常场景处理与实战经验在实际部署中我遇到过几个典型问题假重启问题有时supervisorctl restart命令看似执行成功但实际进程PID未变。解决方案是supervisorctl stop webapp sleep 5 kill -9 $(pgrep -f webapp.jar) 2/dev/null supervisorctl start webapp监控脚本自身挂起添加执行超时控制timeout 30 /opt/scripts/healthcheck.sh || echo Healthcheck timed out /var/log/service-monitor.log服务启动顺序问题依赖数据库的服务可能在DB就绪前启动失败。改进方案[program:webapp] startsecs60 startretries56. 监控系统的自我监控任何监控系统都需要考虑自身可靠性。我采用的保障措施监控脚本监控0 * * * * [ -f /var/log/service-monitor.log ] || (echo Monitor log missing! | mail -s Alert adminexample.com)Supervisor状态检查#!/bin/bash if ! supervisorctl status webapp /dev/null; then systemctl restart supervisor echo Restarted supervisor | mail -s Supervisor was down adminexample.com fiCron任务验证# 检查最近一次执行时间 LAST_RUN$(stat -c %Y /var/log/service-monitor.log) NOW$(date %s) [ $((NOW-LAST_RUN)) -gt 3600 ] echo Cron may not running! | mail -s Alert adminexample.com这套方案在我管理的20多台服务器上稳定运行超过两年将服务不可用时间降低了90%。关键在于定期审查监控日志并根据业务特点调整检查策略。比如电商系统在促销期间应该缩短检查间隔而内部管理系统可以适当放宽标准以节省资源。