Composer中文镜像站凌晨挂因上游变更、同步卡死、磁盘满或rsync权限失效,根源在于缺乏对rsync状态、inotifywait存活及元数据校验的实时感知。

Composer中文镜像站为什么总在凌晨挂?
因为上游源变更、同步脚本卡死、磁盘写满或 rsync 权限失效——这些都不是偶然,而是缺乏对 rsync 进程状态、inotifywait 监听存活、以及 composer.json 元数据校验结果的实时感知。运维不是等报警再爬起来,而是让系统自己盯住 /data/mirror/composer 目录下的每一轮同步日志和 last_sync_time 时间戳。
如何用 Prometheus + Node Exporter 监控核心指标?
只看服务器 CPU 和内存没用,关键得暴露镜像站特有维度:
-
mirror_sync_duration_seconds{repo="packagist"}:记录每次php sync.php --source=packagist耗时,超 1800 秒就标红 -
mirror_file_count{repo="packagist",type="dist"}:对比上游 API 返回的包数量与本地find /data/mirror/composer/dist -name "*.zip" | wc -l,差值 > 50 触发预警 -
disk_avail_bytes{mount="/data"}:低于 20GB 时,自动触发find /data/mirror/composer/cache -mtime +7 -delete
别漏掉 node_filesystem_readonly{mount="/data"} —— ext4 日志满会导致整个 /data 变只读,rsync 静静失败但不报错。
告警规则里必须屏蔽的三个“伪故障”
Alertmanager 的 for 不能设成 1m,否则会因上游临时抖动狂发钉钉消息:
- 上游
packagist.org返回503 Service Temporarily Unavailable是常态,需在 PromQL 中加unless on() (probe_http_status_code{job="upstream-packagist"} == 503) -
inotifywait进程重启时有秒级空窗,用absent(process_start_time_seconds{job="mirror-inotify"})替代单纯查进程存在 - 同步脚本偶发超时重试,应聚合 5 分钟内失败次数:
count_over_time(mirror_sync_failed_total[5m]) > 2才告警
故障自愈脚本真正要做的三件事
自动重启服务只是表象,重点是恢复数据一致性:
- 检测到
rsync异常退出后,先运行rsync --dry-run验证目标路径可写、SSH key 未过期、上游 host key 未变更 - 若
composer show --all在镜像根目录报Could not load package xxx in packages,说明元数据损坏,立即从/data/mirror/composer/.snapshot/last_good恢复packages.json - 所有自愈操作必须写入
/var/log/mirror-heal.log,且日志行首带HEAL:前缀——方便后续用 Filebeat 过滤进 ELK 做归因分析
最常被忽略的是时间戳污染:自愈脚本如果直接 touch 更新 last_sync_time,会掩盖真实同步失败时间。务必用 stat -c "%y" /data/mirror/composer/dist/xxx.zip | head -c 19 取最新文件修改时间反推。


















