Nginx 反向代理配置错误导致磁盘空间耗尽故障复盘
Nginx 反向代理配置错误导致磁盘空间耗尽故障复盘一、事件概述1. 事件背景2026 年 3 月 31 日晚，作者在 Hetzner 小型服务器上部署了数字产品下载服务。服务器配置为 4GB RAM 和 40GB 磁盘空间，提供包括一个 2.2GB 大文件在内的多个文件下载功能。系统架构采用 Haskell 程序处理静态文件服务（包含授权验证），前端使用 nginx 反向代理。2. 影响范围A. 影响用户数数百名付费用户B. 影响时长20:40 - 23:00，持续约 2 小时C. 影响功能所有文件下载功能完全中断（前 2 小时）大文件（2.2GB）下载失败（后续）3. 严重程度P1 级故障（核心业务受损，付费用户无法访问已购买产品）二、事件时间线1. 故障发生（20:40）A. 现象描述产品发布后几分钟内，数百名用户同时访问服务器，系统立即出现磁盘空间不足错误。B. 监控告警日志中出现重复错误信息：user error (Unexpected reply to: MAIL "<...> at kanjideck.com", Expected reply code: 250, Got this instead: 452 "4.3.1 Insufficient system storage")Grafana 显示磁盘使用率 100%（40GB/40GB），df -h 显示 /dev/sda 100% 使用。2. 应急响应（20:40-21:00）A. 初步排查使用 du -sh 分析磁盘占用，发现：/var/lib 下的 Plausible Analytics（ClickHouse 数据库）：8.5GB/nix/store（NixOS 系统配置和可执行文件）：15GB剩余约 20GB 空间来源不明，未进一步分析。B. 处理措施尝试清理 Nix store：nix-collect-garbage -d因磁盘空间不足而失败。清理日志释放空间：journalctl --vacuum-time=1s尝试清理 ClickHouse 日志表：clickhouse-client -q "TRUNCATE TABLE system.query_log"因磁盘空间不足失败。C. 效果评估临时释放少量空间，但系统仍持续消耗磁盘空间，根因未定位。3. 扩容方案（21:00-23:00）A. 实施措施Hetzner 无更大规格实例可用，采用方案 B：购买独立 Volume 挂载 /nix/store。按照 NixOS Wiki 指南迁移 store：fileSystems."/nix" = { device = "/dev/disk/by-label/nix"; fsType = "ext4"; neededForBoot = true; options = [ "noatime" ]; };B. 效果评估服务器重启后，磁盘使用率降至 50%，服务恢复。但大文件下载问题未解决。4. 根本解决（次日）A. 问题定位用户反馈大文件下载中途失败。通过调整 proxy_max_temp_file_size 从默认的 1024m 提升到 5000m，大文件可下载。使用 lsof +L1 发现 14.5GB 已删除但仍被 nginx 占用的临时文件：lsof +L1 | grep nginx # 显示大量 /tmp/nginx_proxy/ 目录下的 deleted 文件B. 根本原因nginx 默认启用响应缓冲，将后端服务器返回的大文件内容缓存到临时文件。proxy_max_temp_file_size 默认值 1024m 限制单个临时文件大小，但多用户并发时产生大量临时文件。C. 解决方案在 nginx 配置中禁用缓冲：extraConfig = '' proxy_buffering off; proxy_max_temp_file_size 0; '';D. 验证结果磁盘使用率降至 20%，不再出现波动。sequenceDiagram participant U as 用户 participant N as Nginx participant T as 临时文件 participant H as Haskell 应用 participant D as 磁盘 U->>N: 下载 2.2GB 文件 N->>H: 代理请求 H-->>N: 返回文件流 N->>T: 写入临时文件（缓冲） T->>D: 占用 1GB 空间 Note over D: 并发 20 用户 = 20GB D-->>N: 磁盘满 N-->>U: 下载失败三、问题分析1. 直接原因nginx 的 proxy_max_temp_file_size 配置不当。默认值 1024m 允许单个请求缓冲最多 1GB 到临时文件，多用户并发下载时快速耗尽磁盘空间。2. 根本原因（5 Whys 分析）A. 为什么出现这个问题？nginx 默认启用响应缓冲机制，当后端响应较大时，会将部分内容写入临时文件。B. 为什么没有及时发现？部署前未进行负载测试，未能模拟多用户并发下载大文件场景。C. 为什么配置不当？对 nginx proxy_buffering 和 proxy_max_temp_file_size 参数理解不足，仅粗略阅读文档。D. 为什么应急处理效率低？压力下未能冷静分析问题，急于清理空间而非定位根因。3. 深层反思文档阅读不够仔细，误以为提高 proxy_max_temp_file_size 可解决问题缺少生产环境部署前的压力测试和容量规划缺少应急处理经验，未建立故障排查清单四、解决方案1. 临时方案A. 实施措施清理 journalctl 日志释放紧急空间将 /nix/store 迁移到独立 VolumeB. 效果评估快速恢复服务，但未根治问题，磁盘使用率仍波动至 65%。2. 永久方案A. 配置修改禁用 nginx 响应缓冲：proxy_buffering off; proxy_max_temp_file_size 0;B. 效果评估磁盘使用率稳定在 20%，不再出现临时文件占用问题。3. 预防措施部署前进行负载测试，模拟真实用户并发场景仔细阅读 nginx 文档，理解每个配置参数的含义建立磁盘空间监控告警，设置阈值（如 80%）准备应急排查清单（lsof +L1、du -sh、df -h）五、经验总结1. 做得好的地方快速响应用户，主动说明问题正在处理在资源受限情况下，找到扩容方案（独立 Volume）最终定位并解决根本原因2. 需要改进的地方应急处理时缺乏系统性思考，急于行动而非分析对关键配置参数理解不深入缺少部署前的测试验证环节3. 技术知识点nginx proxy_buffering：控制是否缓冲后端服务器响应proxy_max_temp_file_size：设置临时文件最大大小，0 表示完全禁用lsof +L1：查找已删除但仍被进程占用的文件4. 最佳实践建议大文件下载场景应禁用 nginx 缓冲，使用流式传输生产部署前必须进行负载测试建立故障排查流程文档，减少应急时的决策压力监控不仅是可用性，还应包含资源使用趋势参考资料Running out of Disk Space in ProductionNginx ngx_http_proxy_module DocumentationNixOS Storage Optimization - Moving the store
EMQX 监控指标完整指南一、概述1. 简介A. 是什么EMQX 监控指标是一套用于监控 EMQX 消息服务器运行状态的数据采集系统。通过调用 EMQX Dashboard API，可以获取节点状态、客户端连接、消息流量、订阅关系等关键指标，并以 Prometheus 格式输出，便于接入监控平台如 Grafana、Prometheus 等。B. 为什么需要EMQX 作为物联网消息中间件，承载着设备连接和数据转发的重要任务。通过监控指标可以：实时掌握集群健康状态及时发现性能瓶颈快速定位故障原因评估系统容量规划C. 学完能做什么部署 EMQX 监控采集脚本理解各项监控指标的含义配置 Grafana 监控面板建立告警规则保障系统稳定2. 前置知识A. 必备技能基本 Linux 命令操作了解 MQTT 协议基础概念熟悉 Prometheus 监控体系B. 推荐知识Categraf 采集器使用Grafana 面板配置Shell 脚本基础二、环境准备1. 系统要求EMQX 5.x 版本Linux 操作系统（Ubuntu、CentOS 等）具备访问 EMQX Dashboard API 的权限已安装 Categraf 或其他 Prometheus 兼容的采集器2. 组件说明监控脚本通过调用 EMQX RESTful API 获取数据，主要涉及以下端点：/api/v5/nodes：获取节点基础信息/api/v5/metrics：获取详细指标数据/api/v5/clients：获取客户端统计/api/v5/subscriptions：获取订阅统计/api/v5/topics：获取 Topic 统计3. 认证配置EMQX API 使用 HTTP Basic Authentication，需要提供 API Key 和 Secret：export EMQX_API_KEY="your_api_key" export EMQX_API_SECRET="your_api_secret" export EMQX_API_URL="http://emqx-server:18083/api/v5/nodes"三、监控架构1. 数据采集流程graph LR A[Categraf] -->|定时执行| B[监控脚本] B -->|HTTP请求| C[EMQX API] C -->|JSON响应| B B -->|Prometheus格式| D[采集器] D -->|推送| E[后端存储]2. 指标分类体系EMQX 监控指标按功能划分为 8 大类：mindmap root((EMQX监控指标)) 节点基础 连接数 内存使用 系统负载 进程状态 客户端 连接统计 认证状态 授权记录 消息 收发统计 QoS分布 丢弃率 数据包 包类型统计 传输状态 会话 创建终止 状态管理 订阅 订阅数量 创建统计 Topic 活跃数量 分布统计 字节 流量统计 带宽使用四、指标详解1. 节点基础指标节点基础指标反映 EMQX 集群中每个节点的运行状态，是监控系统最核心的部分。A. 连接类指标指标名称指标类型说明emqx_connectionsgauge当前连接数，反映当前客户端连接总数emqx_live_connectionsgauge活跃连接数，排除空闲连接emqx_cluster_sessionsgauge集群会话总数，跨节点的会话汇总B. 系统资源指标指标名称指标类型说明emqx_load1gauge系统 1 分钟平均负载emqx_load5gauge系统 5 分钟平均负载emqx_load15gauge系统 15 分钟平均负载emqx_memory_usedgauge已使用内存（字节）emqx_memory_totalgauge总内存（字节）emqx_process_usedgaugeErlang 进程已使用数emqx_process_availablegaugeErlang 进程可用数C. 运行状态指标指标名称指标类型说明emqx_uptimegauge节点运行时长（秒）emqx_max_fdsgauge最大文件描述符数emqx_node_statusgauge节点状态，1 表示运行，0 表示停止2. 客户端指标客户端指标用于监控连接到 EMQX 的设备状态和认证情况。A. 连接统计指标名称指标类型说明emqx_clients_countgauge当前连接的客户端总数emqx_clients_connected_totalcounter累计连接的客户端数，自节点启动以来emqx_clients_disconnected_totalcounter累计断开的客户端数B. 认证授权指标名称指标类型说明emqx_clients_authenticate_totalcounter认证请求总数emqx_clients_auth_success_totalcounter认证成功总数emqx_clients_auth_failure_totalcounter认证失败总数，可用于安全审计3. 订阅指标订阅指标反映客户端对 Topic 的订阅情况。指标名称指标类型说明emqx_subscriptions_countgauge当前订阅总数emqx_subscriptions_created_totalcounter累计创建订阅数4. Topic 指标Topic 指标用于监控消息主题的使用情况。指标名称指标类型说明emqx_topics_countgauge当前活跃 Topic 总数5. 消息指标消息指标是监控 EMQX 消息流转的核心指标，反映系统的消息处理能力。A. 消息总体统计指标名称指标类型说明emqx_messages_received_totalcounter接收消息总数emqx_messages_sent_totalcounter发送消息总数emqx_messages_publish_totalcounter发布消息总数emqx_messages_acked_totalcounter已确认消息总数emqx_messages_delivered_totalcounter已投递消息总数B. 消息丢弃统计指标名称指标类型说明emqx_messages_dropped_totalcounter丢弃消息总数，需重点关注emqx_messages_dropped_no_subscribers_totalcounter因无订阅者而丢弃的消息数C. QoS 级别消息统计指标名称指标类型说明emqx_messages_qos0_received_totalcounter接收的 QoS0 消息数，最多一次emqx_messages_qos0_sent_totalcounter发送的 QoS0 消息数emqx_messages_qos1_received_totalcounter接收的 QoS1 消息数，至少一次emqx_messages_qos1_sent_totalcounter发送的 QoS1 消息数D. 消息转发指标名称指标类型说明emqx_messages_forward_totalcounter转发消息总数，集群场景下重要6. 数据包指标数据包指标反映 MQTT 协议层的传输情况。指标名称指标类型说明emqx_packets_received_totalcounter接收数据包总数emqx_packets_sent_totalcounter发送数据包总数emqx_packets_publish_received_totalcounter接收的 PUBLISH 包数emqx_packets_publish_sent_totalcounter发送的 PUBLISH 包数7. 会话指标会话指标反映 MQTT 会话的生命周期管理。指标名称指标类型说明emqx_sessions_created_totalcounter创建会话总数emqx_sessions_terminated_totalcounter终止会话总数8. 字节传输指标字节指标反映网络带宽使用情况。指标名称指标类型说明emqx_bytes_received_totalcounter接收字节总数emqx_bytes_sent_totalcounter发送字节总数五、快速部署1. 部署监控脚本A. 创建脚本目录mkdir -p /opt/categraf/conf/input.exec cd /opt/categraf/conf/input.execB. 编写监控脚本将 emqx_monitor.sh 脚本放置到指定目录，并赋予执行权限：chmod +x /opt/categraf/conf/input.exec/emqx_monitor.shC. 配置环境变量编辑配置文件 /opt/categraf/conf/input.exec/emqx_monitor.conf：export EMQX_API_KEY="your_api_key" export EMQX_API_SECRET="your_api_secret" export EMQX_API_URL="http://10.10.74.101:18083/api/v5/nodes" export EMQX_MIDD_PROJECT="new-iot" export EMQX_MIDD_TYPE="emqx"2. 配置 Categraf编辑 Categraf 配置文件 /opt/categraf/conf/input.exec/exec.toml：instances commands = [ "/opt/categraf/conf/input.exec/emqx_monitor.sh" ] data_format = "prometheus" prometheus_ignore_timestamp = true3. 测试验证A. 手动执行脚本/opt/categraf/conf/input.exec/emqx_monitor.sh预期输出：Prometheus 格式的指标数据B. Categraf 测试/opt/categraf/categraf -inputs exec -test -debug预期输出：解析后的指标数据六、告警规则建议1. 核心告警指标告警名称指标触发条件严重级别节点宕机emqx_node_status值为 0严重连接数过高emqx_connections超过阈值警告消息丢弃率emqx_messages_dropped_total增长率异常警告认证失败emqx_clients_auth_failure_total短时间大量失败严重内存使用率emqx_memory_used超过 80%警告2. 告警规则示例groups: - name: emqx_alerts rules: - alert: EMQXNodeDown expr: emqx_node_status == 0 for: 1m labels: severity: critical annotations: summary: "EMQX 节点宕机" - alert: EMQXHighConnectionCount expr: emqx_connections > 10000 for: 5m labels: severity: warning annotations: summary: "连接数超过阈值"七、常见问题1. 脚本执行问题A. 权限不足现象：脚本无法执行解决：检查脚本执行权限 chmod +x emqx_monitor.shB. API 认证失败现象：返回 401 或 403 错误解决：检查 API Key 和 Secret 是否正确2. 指标采集问题A. 指标缺失现象：部分指标没有数据解决：确认 EMQX 版本是否支持对应指标B. 数据格式错误现象：Categraf 无法解析解决：检查 data_format 配置是否为 prometheus3. 性能问题A. 采集频率过高现象：频繁调用 API 影响性能解决：调整采集间隔，建议 15 秒以上B. 超时问题现象：脚本执行超时解决：增加 CURL_TIMEOUT 参数值八、最佳实践1. 监控体系设计graph TB A[EMQX 集群] --> B[监控采集] B --> C[Prometheus] C --> D[Grafana] D --> E[可视化面板] C --> F[告警规则] F --> G[告警通知]2. 面板设计建议概览面板：展示核心指标趋势节点面板：分节点展示详细信息业务面板：按业务维度统计消息量3. 告警分级严重告警：立即处理，如节点宕机警告告警：关注处理，如连接数偏高提示告警：记录分析，如偶发认证失败参考资料EMQX 官方文档 - APICategraf 使用指南Prometheus 监控最佳实践
Linux MCE 硬件错误监控完全指南一、概述1. 简介A. 是什么MCE（Machine Check Exception）是 x86/x86-64 架构的硬件错误检测机制，用于捕获和记录 CPU、内存、电源等硬件故障。B. 为什么需要硬件故障可能导致系统突然崩溃，启用 MCE 可以：记录详细的硬件错误信息定位故障根源（CPU、内存、电源等）避免盲目排查浪费时间C. 学完能做什么检查系统 MCE 启用状态定位 MCE 日志存储位置分析硬件错误类型编写自动化检查脚本2. 前置知识A. 必备技能基本 Linux 命令操作了解 journalctl 和 dmesg 基础用法B. 推荐知识系统日志管理硬件监控概念二、核心概念1. 基本术语MCE：Machine Check Exception，机器检查异常mcelog：MCE 日志守护进程（可选）/dev/mcelog：MCE 字符设备，用于读取错误信息2. 工作原理graph TD A[硬件错误发生] --> B{MCE 是否启用?} B -->|是| C[内核捕获错误] C --> D[记录到 /dev/mcelog] D --> E[写入 dmesg] E --> F[写入 systemd journal] F --> G[系统优雅处理或重启] B -->|否| H[错误未被捕获] H --> I[系统直接崩溃] I --> J[无日志记录]3. GRUB 参数mce=off：禁用 MCE 机制（不推荐）mce=on：启用 MCE（默认）mce=bootlog：仅记录启动时的 MCEmce=infinite：只记录一次，不中断系统三、MCE 日志存储位置1. 日志存储架构graph LR A[硬件错误] --> B[/dev/mcelog 字符设备] B --> C[dmesg 内核缓冲区] B --> D[systemd journal 持久化存储] C --> E[重启后丢失] D --> F[持久保存]2. 各位置详解A. /dev/mcelog（字符设备）位置：/dev/mcelog类型：字符设备 (10, 227)权限：crw-------（仅 root 可读）持久性：实时输出，设备级# 检查设备是否存在 ls -l /dev/mcelog # 读取原始内容（无错误时为空） dd if=/dev/mcelog bs=64 count=1B. dmesg（内核消息缓冲区）位置：内核 ring buffer持久性：重启后丢失用途：快速查看当前启动的错误# 查看 MCE 相关消息 dmesg | grep -i 'mce\|machine check' # 带时间戳查看 dmesg -T | grep -i mceC. systemd journal（持久化日志）⭐ 推荐位置：/var/log/journal/*/system.journal持久性：持久保存用途：历史查询和长期存储# 查看当前启动的 MCE 日志 journalctl -k -b 0 | grep -i 'mce\|hardware machine' # 查看上次启动的 MCE 日志 journalctl -k -b -1 | grep -i mce # 查看所有历史 MCE 日志 journalctl -k | grep -i mce四、检查 MCE 状态1. 验证 MCE 是否启用A. 检查内核启动参数# 查看当前内核参数 cat /proc/cmdline # 检查是否包含 mce=off cat /proc/cmdline | grep -o 'mce=[^ ]*' # 如果没有输出，说明 MCE 未被禁用（正常）B. 检查 MCE 设备# 检查 /dev/mcelog 设备 ls -l /dev/mcelog # 正常输出示例 # crw------- 1 root root 10, 227 Apr 2 21:45 /dev/mcelog # 如果设备不存在，说明 MCE 被禁用或初始化失败C. 检查内核初始化日志# 查看是否有 MCE 初始化错误 journalctl -k | grep 'mce: Unable' # 如果看到 "mce: Unable to init MCE device" 说明 MCE 被禁用2. 快速检查脚本创建 /root/check_mce.sh：#!/bin/bash echo '=== MCE 硬件错误检查 ===' echo '' echo '1. 检查 /dev/mcelog 设备:' ls -l /dev/mcelog 2>/dev/null || echo ' ❌ MCE设备不存在' echo '' echo '2. 检查内核启动参数:' cat /proc/cmdline | grep -o 'mce=[^ ]*' || echo ' ✓ MCE未禁用' echo '' echo '3. 当前启动的MCE日志:' journalctl -k -b 0 --no-pager | grep -i 'mce\|hardware machine' || echo ' ✓ 无MCE事件' echo '' echo '4. 历史MCE日志:' journalctl -k --no-pager | grep -i 'mce\|hardware machine' | tail -20 || echo ' ✓ 历史无MCE事件'使用方法：chmod +x /root/check_mce.sh /root/check_mce.sh五、MCE 故障排查1. 启用 MCE（如果被禁用）A. 检查 GRUB 配置cat /etc/default/grub如果看到 mce=off：# GRUB_CMDLINE_LINUX_DEFAULT=" intel_idle.max_cstate=1 mce=off"B. 修改配置# 备份配置文件 cp /etc/default/grub /etc/default/grub.bak.$(date +%Y%m%d_%H%M%S) # 移除 mce=off sed -i 's/mce=off//g' /etc/default/grub # 更新 GRUB update-grub # 重启系统 rebootC. 验证修改# 重启后检查 cat /proc/cmdline # 应该不再包含 mce=off # 检查 /dev/mcelog 设备 ls -l /dev/mcelog2. MCE 事件类型A. 常见错误类型错误类型说明严重程度corrected error已纠正的错误低uncorrected error未纠正的错误高fatal error致命错误极高B. MCE 日志示例# CPU 硬件错误示例 [12345.678904] mce: [Hardware Error]: CPU 0: Machine Check Event: 0 Bank 0 [12345.678906] mce: [Hardware Error]: TSC 0 addr 0 RIP 10 # 内存错误示例 [12345.678904] mce: [Hardware Error]: Machine check event logged on CPU 0 [12345.678906] mce: [Hardware Error]: Bank 0: b200000000070f0f (corrected error)3. 故障发生时的检查流程flowchart TD A[系统崩溃重启] --> B[运行 check_mce.sh] B --> C{有 MCE 日志?} C -->|有| D[分析错误类型] D --> E{错误类型} E -->|CPU错误| F[更换CPU或主板] E -->|内存错误| G[运行内存测试 更换故障内存] E -->|热过载| H[检查散热 清理灰尘] E -->|电源异常| I[检查电源供应] C -->|无| J[检查其他日志 可能非硬件问题]六、实用命令速查1. 状态检查命令# 检查 MCE 设备 ls -l /dev/mcelog # 检查内核参数 cat /proc/cmdline | grep mce # 检查系统运行时间 uptime # 检查温度 sensors2. 日志查看命令# 查看当前启动的 MCE 日志 journalctl -k -b 0 | grep -i mce # 查看上次启动的 MCE 日志 journalctl -k -b -1 | grep -i mce # 查看所有历史 MCE 日志 journalctl -k | grep -i mce # 实时监控 MCE 事件 journalctl -k -f | grep -i mce # dmesg 快速查看 dmesg | grep -i 'mce\|machine check'3. 对比命令# 对比两次启动的内核参数 journalctl -k -b -1 | grep 'Command line' journalctl -k -b 0 | grep 'Command line' # 对比 MCE 初始化状态 journalctl -k -b -1 | grep 'mce: Unable' journalctl -k -b 0 | grep 'mce: Unable'七、常见问题1. MCE 被禁用现象cat /proc/cmdline # 显示 ... mce=off解决方案参考"五、1. 启用 MCE"章节2. /dev/mcelog 不存在现象ls -l /dev/mcelog # ls: cannot access '/dev/mcelog': No such file or directory原因分析MCE 被禁用内核不支持 MCEMCE 初始化失败解决方案# 检查内核日志 journalctl -k | grep -i mce # 如果看到 "mce: Unable to init MCE device" # 检查 GRUB 配置并移除 mce=off3. 系统崩溃但无 MCE 日志可能原因MCE 未启用非硬件故障（软件问题）日志轮转导致历史日志丢失排查步骤# 1. 确认 MCE 启用 /root/check_mce.sh # 2. 检查其他日志 journalctl -b -1 | tail -100 # 3. 检查系统日志 journalctl -b -1 -p err八、最佳实践1. 监控建议定期运行 /root/check_mce.sh配置 systemd journal 持久化设置日志轮转策略2. 预防措施清理机箱灰尘检查风扇运转运行内存测试（memtest86+）监控温度变化3. 老化硬件特别说明对于 3 年以上的服务器：增加检查频率准备备用硬件考虑硬件升级计划建立硬件故障响应流程参考资料Linux Kernel MCE DocumentationGRUB Configuration Guide
Zookeeper 容器连接超时故障复盘一、事件概述1. 事件背景生产环境 Zookeeper 容器每天需要手动重启一次，否则会出现端口通但无法连接的问题。容器已运行 20 个月，问题近期频繁出现。2. 影响范围A. 影响用户数依赖 Zookeeper 的所有业务系统B. 影响时长问题累积约 24 小时后必须重启C. 影响功能服务注册发现、分布式协调、配置管理3. 严重程度P2 级故障（影响业务可用性，需每日人工干预）二、事件时间线1. 问题发现A. 现象描述端口 2181 可以 telnet 通客户端连接超时或失败重启容器后恢复正常B. 问题特征容器运行时间越长，问题越严重每天需要手动重启一次服务器：192.168.124.48（已脱敏）容器：confluentinc/cp-zookeeper:7.3.22. 问题诊断A. 日志分析通过日志分析发现配置问题：tickTime=3000 minSessionTimeout=6000 maxSessionTimeout=60000 (只有 60 秒) clientPortListenBacklog=-1B. 根因定位maxSessionTimeout 只有 60 秒，长连接客户端被断开clientPortListenBacklog 使用系统默认值，高负载时连接队列问题无自动重启策略，异常时无法自动恢复3. 解决方案实施sequenceDiagram participant O as 运维人员 participant S as 服务器 participant Z as Zookeeper O->>S: 创建配置文件 O->>Z: 停止旧容器 Note over Z: 容器卡住需强制删除 O->>S: kill 僵死进程 O->>Z: 强制删除容器 O->>Z: 创建新容器 Z-->>O: 启动成功 O->>Z: 验证配置三、问题分析1. 直接原因A. Session Timeout 配置过小maxSessionTimeout 只有 60 秒（20 × tickTime），对于需要长连接的客户端来说太短。B. 连接队列配置不当clientPortListenBacklog=-1，使用系统默认值，在高负载或连接累积情况下可能导致连接队列问题。C. 无自动重启机制RestartPolicy=no，容器异常时不会自动重启。2. 根本原因（5 Whys 分析）A. 为什么出现连接问题？Session 超时时间过短，客户端长连接被服务端主动断开。B. 为什么超时时间过短？使用默认配置，未根据业务场景调整参数。C. 为什么没有自动恢复？容器未配置自动重启策略。D. 为什么配置不当？缺乏容器化中间件的配置规范和最佳实践。3. 配置影响分析graph TB A[配置不当] --> B[maxSessionTimeout=60s] A --> C[clientPortListenBacklog=-1] A --> D[RestartPolicy=no] B --> E[长连接断开] C --> F[连接队列溢出] D --> G[异常无法自愈] E --> H[客户端连接失败] F --> H G --> I[需人工重启] H --> J[业务受影响] I --> J四、解决方案1. 临时方案A. 实施措施每天手动重启容器B. 效果评估临时恢复服务需持续人工干预治标不治本2. 永久方案A. 配置优化创建自定义配置文件 zookeeper.properties：tickTime=2000 dataDir=/var/lib/zookeeper/data dataLogDir=/var/lib/zookeeper/log clientPort=2181 initLimit=10 syncLimit=5 maxSessionTimeout=300000 minSessionTimeout=4000 clientPortListenBacklog=1024 server.1=zookeeper:2888:3888B. 容器重新创建docker run -d \ --name zookeeper \ --restart=unless-stopped \ --network root_yewu-network \ -p 2181:2181 \ -p 1812:2181 \ -v /root/data/zookeeper/data:/var/lib/zookeeper/data \ -v /root/data/zookeeper/log:/var/lib/zookeeper/log \ -v /root/data/zookeeper/secrets:/etc/zookeeper/secrets \ -v /root/data/zookeeper/zookeeper.properties:/etc/kafka/zookeeper.properties \ -e ZOOKEEPER_CLIENT_PORT=2181 \ -e ZOOKEEPER_SERVER_ID=1 \ -e ZOOKEEPER_SERVERS=zookeeper:2888:3888 \ harbor.op123.ren:44301/confluentinc/cp-zookeeper:7.3.2C. 关键参数变更参数修复前修复后说明tickTime3000ms2000ms基准时间单位maxSessionTimeout60秒300秒5分钟，足够长连接使用minSessionTimeout6秒4秒最小会话超时clientPortListenBacklog-11024连接队列大小RestartPolicynounless-stopped自动重启3. 预防措施A. 建立配置规范为常用中间件制定标准配置模板B. 健康检查机制配置容器健康检查和监控告警C. 定期巡检定期检查容器运行状态和配置参数五、经验总结1. 做得好的地方通过日志分析准确定位根因使用配置文件挂载方式，便于后续维护配置自动重启策略，提高可用性2. 需要改进的地方缺少容器化中间件的配置规范缺少监控告警机制问题存在时间较长才处理3. 流程优化建议A. 中间件部署规范制定统一的中间件容器化部署规范，包括：必须配置自动重启策略关键参数需要根据业务场景调整配置文件外部化管理B. 监控告警体系添加 Zookeeper 连接数监控添加容器健康状态监控配置异常自动告警C. 定期巡检机制每周检查容器运行状态每月检查配置参数合理性定期更新镜像版本六、配置参考1. Zookeeper 核心参数说明参数默认值推荐值说明tickTime20002000ZK 时间单位（毫秒）initLimit1010初始连接同步超时（tickTime 数）syncLimit55同步请求超时（tickTime 数）maxSessionTimeout60000300000最大会话超时（毫秒）minSessionTimeout60004000最小会话超时（毫秒）clientPortListenBacklog-11024连接队列大小2. 容器启动最佳实践必须配置 --restart 策略数据目录必须持久化挂载配置文件外部化管理配置健康检查机制添加资源限制（memory、CPU）参考资料Apache Zookeeper 官方文档Confluent Platform Zookeeper 配置
服务器 MCE 硬件错误诊断与监控实施案例
服务器 MCE 硬件错误诊断与监控实施案例一、事件概述1. 事件背景服务器 xlab-ecs-node2（192.168.86.152）在运行过程中出现 MCE（Machine Check Exception）硬件错误，系统自动重启。该服务器是一台使用超过 10 年的老旧设备，配备 Intel Xeon E5-2697 v2 处理器。2. 影响范围A. 影响用户数内部开发测试环境用户B. 影响时长系统频繁重启，单次运行时间仅 2-5 分钟C. 影响功能所有部署在该服务器上的服务3. 严重程度P2 级故障（硬件老化，存在服务中断风险）二、事件时间线1. 问题发现（2026-04-01 01:18）A. 现象描述系统日志显示大量 MCE 错误，服务器自动重启B. 监控告警journalctl -b -p err | grep mce显示超过 300 条 MCE 硬件错误记录2. 初步诊断（2026-04-01 01:19）A. 发现途径SSH 登录服务器查看内核日志B. 初步判断MCE Bank 7：QPI/L3 缓存错误MCE Bank 10：内存控制器错误错误类型：已纠正的 ECC 错误3. 监控方案实施（2026-04-01 01:20-01:24）A. 处理措施安装 rasdaemon（Ubuntu 22.04 已弃用 mcelog）配置 RAS 子系统监控创建自动化监控脚本设置定时任务每 5 分钟检查B. 效果评估监控体系建立完成，可实时追踪硬件错误变化4. 诊断完成（2026-04-01 01:25）A. 诊断结论问题定位于 CPU 内存控制器子系统退化，非内存条故障B. 验证结果EDAC 显示所有 DIMM 的 ECC 错误计数为 0sequenceDiagram participant S as 服务器 participant O as 运维人员 participant M as 监控系统 S->>O: 01:18 MCE 错误告警 O->>S: 01:19 SSH 登录诊断 S->>O: 返回内核日志 O->>S: 01:20 安装 rasdaemon S->>M: 01:22 启动 RAS 监控 O->>S: 01:23 部署监控脚本 S->>M: 01:24 定时任务就绪 O->>O: 01:25 生成诊断报告三、问题分析1. 直接原因MCE Bank 7 和 Bank 10 错误表明问题发生在 CPU 内存控制器子系统，具体包括：QPI（QuickPath Interconnect）链路错误内存控制器内部 ECC 错误L3 缓存错误2. 根本原因（5 Whys 分析）A. 为什么出现这个问题？CPU 内存控制器电气特性退化，信号完整性下降B. 为什么信号完整性下降？硬件使用超过 10 年（2013 年发布），超过设计寿命C. 为什么 EDAC 显示 DIMM 无错误？MCE Bank 7/10 错误发生在 CPU 内部，而非 DIMM 模块D. 为什么没有提前发现？缺少硬件监控告警机制E. 深层反思老旧硬件缺少完善的监控体系，无法提前预警硬件退化3. 数据分析错误分布统计错误类型数量占比Bank 7（QPI/L3）15250.2%Bank 10（内存控制器）15149.8%受影响 CPU 核心CPU 23、22、20、19、18：各 36 个错误其他核心：1-4 个错误不等错误率评估303 个错误 / 5 分钟运行时间 ≈ 60 错误/分钟四、解决方案1. 监控方案（已实施）A. 实施措施# 安装 RAS 守护进程 apt-get install -y rasdaemon systemctl enable rasdaemon systemctl start rasdaemon # 部署监控脚本 /usr/local/bin/mce-monitor.sh # 每 5 分钟检查 /usr/local/bin/mce-analyze.sh # 手动详细分析B. 监控指标MCE 错误总数错误分布（按 CPU 核心）错误类型（Bank 7 / Bank 10）系统运行时间2. 临时缓解措施（建议）A. 实施措施降低内存负载，减少运行服务数量增加 swap 分区缓解内存压力确保数据备份完整B. 效果评估可延长系统稳定运行时间，但无法根治3. 永久解决方案（推荐）A. 硬件维护检查主板电容和供电模块清理灰尘，改善散热重插所有内存模块B. 硬件更换1-3 个月内更换服务器，迁移到更新的硬件平台五、监控体系架构1. 监控组件graph TB Kernel[Linux 内核] -->|MCE 事件| RAS[RAS 子系统] RAS --> rasdaemon[rasdaemon 服务] rasdaemon --> EDAC[EDAC 驱动] EDAC --> mc0[mc0 控制器] EDAC --> mc1[mc1 控制器] rasdaemon --> Log[日志记录] Cron[cron 定时任务] --> Monitor[mce-monitor.sh] Monitor --> Alert[告警输出]2. 日志文件结构日志文件用途/var/log/mce/mce-errors.log详细 MCE 错误记录/var/log/mce/mce-summary.log监控摘要/var/log/mce/mce-cron.log定时任务执行日志/var/log/mce/diagnostic-report-*.txt完整诊断报告3. 监控命令速查# 实时监控 MCE 事件 journalctl -kf | grep mce # 查看 RAS 错误摘要 ras-mc-ctl --summary # 手动运行检查 /usr/local/bin/mce-monitor.sh # 生成详细分析 /usr/local/bin/mce-analyze.sh六、经验总结1. 做得好的地方快速定位问题根源（CPU 级别而非内存条）建立了完善的监控体系生成详细的诊断报告2. 需要改进的地方老旧硬件应提前部署监控需要配置告警通知机制应建立硬件生命周期管理3. 最佳实践总结使用 rasdaemon 替代已弃用的 mcelog（Ubuntu 22.04+）MCE Bank 7/10 错误通常是 CPU 内存控制器问题EDAC 显示 DIMM 无错误不代表内存系统健康老旧硬件必须部署硬件监控4. 技术要点MCE Bank 错误解读Bank含义严重程度Bank 0-4缓存错误中等Bank 5内存错误高Bank 6总线/互连错误中等Bank 7QPI/L3 错误高Bank 8TLB 错误低Bank 10内存控制器错误高ECC 错误类型CE（Correctable Error）：已纠正错误，系统继续运行UE（Uncorrectable Error）：不可纠正错误，导致系统 panic七、后续行动1. 短期（1 周内）每日检查 MCE 错误日志评估错误率变化趋势准备硬件维护计划2. 中期（1 个月内）安排服务器硬件维护测试备份服务器制定迁移计划3. 长期（3 个月内）完成服务器更换迁移所有服务到新硬件建立硬件生命周期管理制度参考资料Linux RAS 子系统文档Intel Machine-Check Architecture
GitHub 可用性危机分析：三个九都难以维持
GitHub 可用性危机分析：三个九都难以维持一、新闻概述1. 标题GitHub 在勉强维持三个九的可用性方面举步维艰2. 发布时间2026 年 2 月 10 日 12:39 UTC3. 来源The Register（技术媒体）二、核心内容1. 事件摘要A. 主要内容GitHub 近期频繁出现服务中断和性能问题，其可用性甚至难以维持三个九（99.9%）的标准。B. 核心亮点2026 年 2 月 9 日发生多起服务故障Actions、Pull Requests、通知和 Copilot 全部受影响通知延迟长达 50 分钟Copilot 策略传播问题持续 17 小时2025 年某个时段正常运行时间曾降至 90% 以下2. 关键信息A. 故障时间2026 年 2 月 9 日 15:54 UTC 开始确认问题B. 受影响服务GitHub ActionsPull Requests通知服务GitHub CopilotC. 恢复时间2026 年 2 月 9 日 19:29 UTC 确认恢复正常3. 背景介绍A. 服务等级协议GitHub Enterprise Cloud 的 SLA 规定 99.9% 的正常运行时间，但不对所有用户做出保证。B. 行业标准五个九（99.999% 的正常运行时间）是云计算行业的金标准，但许多供应商连 90% 都难以维持。三、详细报道1. 主要故障事件A. 2026 年 2 月 9 日服务中断graph LR T1[15:54 UTC] --> A[确认部分 GitHub 服务出现问题] T2[16:29 UTC] --> B[Copilot 策略传播问题开始] T3[17:57 UTC] --> C[通知延迟降至约 30 分钟] T4[19:29 UTC] --> D[确认服务恢复正常] T5[次日 09:57 UTC] --> E[Copilot 问题完全解决] style T1 fill:#e1f5ff style T2 fill:#ffe1e1 style T3 fill:#fff4e1 style T4 fill:#e1ffe1 style T5 fill:#e1e1ff问题详情：通知延迟：最高达 50 分钟Copilot 策略传播：新启用的模型无法在用户访问时显示故障持续时间：约 3.5 小时（主要服务）Copilot 故障：持续约 17 小时B. 历史可用性问题根据非官方重建的状态页面数据，GitHub 在 2025 年某个时段的正常运行时间曾降至 90% 以下。2. 技术细节A. 可用性标准对比可用性等级正常运行时间年度停机时间适用场景一个九90%36.5 天消费级服务两个九99%3.65 天一般业务三个九99.9%8.76 小时企业服务（GitHub SLA）四个九99.99%52.56 分钟高可用服务五个九99.999%5.26 分钟关键基础设施B. 状态页面变更GitHub 更新了其状态页面的设计，使得以下操作变得更加困难：查看过去 90 天的整体运行情况可视化服务的整体可用性快速评估系统稳定性3. 相关事件graph LR A[GitHub 服务问题] --> B[Actions 故障] A --> C[Pull Requests 故障] A --> D[通知延迟] A --> E[Copilot 故障] B --> F[CI/CD 中断] C --> G[代码协作受阻] D --> H[团队沟通延迟] E --> I[AI 编程助手失效]四、影响分析1. 对开发者的影响A. 开发工作流中断CI/CD 管道因 Actions 故障而停止代码审查和合并流程受阻团队协作效率下降B. AI 编程辅助失效Copilot 服务中断影响开发者生产力策略传播问题导致新模型无法访问2. 对企业客户的影响A. SLA 争议Enterprise Cloud SLA 规定 99.9% 正常运行时间实际可用性可能难以达到承诺标准B. 业务连续性风险频繁的服务中断影响关键开发项目需要制定故障应急预案3. 行业影响A. 云服务可靠性信任危机云服务难以维持基本的可用性标准五个九的承诺在现实中难以实现B. 微软旗下服务稳定性质疑GitHub 作为微软子公司，其服务质量引发关注与其他微软服务的稳定性问题相呼应五、各方反应1. 用户反馈社区对 GitHub 频繁故障表示不满开发者担心依赖单一平台的风险2. 行业观察云服务可靠性普遍下降企业应规划故障应对策略3. 相关报道Zig 编程语言因微软 AI 痴迷而退出 GitHubGitHub 计划对自托管运行器收费后撤回决定六、经验教训1. 服务设计启示A. 透明度问题状态页面设计变更降低了透明度用户难以评估服务的整体可用性B. 监控与告警需要独立的第三方监控用户应自行监控关键服务2. 客户应对策略A. 多平台部署避免过度依赖单一代码托管平台考虑自托管或混合部署方案B. 故障预案制定服务中断时的应急预案建立离线工作能力3. 行业思考A. SLA 现实性供应商需要更现实的可用性承诺客户应理性评估 SLA 条款B. 可靠性投资云服务商需要投资基础设施可靠性简化架构以提高稳定性参考资料GitHub appears to be struggling with measly three nines availability - The Register
修复 mcporter 与 n9e-mcp-server SSE 连接挂起问题一、事件概述1. 事件背景用户在使用 mcporter 调用 Nightingale MCP 工具时，程序出现挂起现象。mcporter list 显示 nightingale 服务为 offline 状态，执行 mcporter call nightingale.list_active_alerts 命令时程序无响应。2. 影响范围A. 影响功能Nightingale MCP 工具调用全部失败无法通过 MCP 协议访问 Nightingale 监控数据影响 list_active_alerts、list_history_alerts 等所有监控工具B. 影响时长调试过程持续约 2 小时，涉及多次代码修改和验证3. 严重程度P2 级问题，影响特定 MCP 服务器的可用性二、事件时间线1. 问题发现（初始阶段）A. 现象描述执行 mcporter list 时，nightingale 显示为 "offline — unable to reach server"B. 初步判断根据计划文件，问题根源是配置不匹配：mcporter 配置使用 stdio 模式，但 n9e-mcp-server 已切换到 HTTP SSE 模式运行。2. 配置调整（第一阶段）A. 处理措施修改 /home/jacky/.claude/config/mcporter.json，将 nightingale 从 stdio 模式改为 HTTP SSE 模式B. 效果评估问题未解决，mcporter list 仍显示 nightingale 为 offline3. 用户关键反馈（第二阶段）A. 发现途径用户注意到服务器日志中 session_id 为空字符串：session_id=""B. 用户提问"from the log i see session_id is null, shall this is the problem?"4. SessionID 调查（第三阶段）A. 调研方法通过 zread 工具检查 go-sdk 源代码 mcp/sse.goB. 关键发现在 sseServerConn 和 sseClientConn 的 SessionID 方法中发现以下注释：// TODO(jba): get the session ID. (Not urgent because SSE transports have been removed from the spec.) func (s *sseServerConn) SessionID() string { return "" }C. 结论空的 session_id 是预期行为，SSE 传输已从 MCP 规范中移除，不是问题根源5. 真实问题定位（第四阶段）A. 处理措施使用 curl 直接测试 SSE 端点，验证服务器是否正常响应B. 关键发现curl 测试成功，SSE 流程正常工作。问题在于 mcporter 的传输模式回退逻辑：尝试 Streamable HTTP 模式：失败，提示 "sessionid must be provided"回退到 SSE 模式：挂起6. 配置文件定位（第五阶段）A. 处理措施搜索并确认 mcporter 的实际配置文件位置B. 关键发现mcporter 使用 /home/jacky/.mcporter/mcporter.json，而非 /home/jacky/.claude/config/mcporter.jsonC. 修复措施更新正确的配置文件，将 URL 从远程地址改为本地地址7. Token 认证逻辑修复（第六阶段）A. 问题分析检查 n9e-mcp-server 的 HTTP 处理代码，发现所有请求（包括 POST 到 session endpoint）都强制要求 token 认证B. 问题根因POST 请求到 /mcp?sessionid=XXX 时，这些请求应仅使用 sessionid 认证，不应再次验证 tokenC. 修复措施修改 /mydata/code/mcp/n9e-mcp-server/internal/http_server.go，添加条件判断：mainHandler.HandleFunc("/mcp", func(w http.ResponseWriter, r *http.Request) { // POST 请求带 sessionid 直接转发到 SSE handler if r.Method == http.MethodPost && r.URL.Query().Get("sessionid") != "" { sseHandler.ServeHTTP(w, r) return } // 其他请求需要 token 认证 token := r.URL.Query().Get("token") if token == "" { http.Error(w, "token parameter required", http.StatusUnauthorized) return } sseHandler.ServeHTTP(w, r) })D. 效果评估mcporter list 成功显示 "nightingale (27 tools, 0.1s)"，SSE 连接正常建立8. Nightingale API 401 问题（第七阶段）A. 现象描述SSE 连接正常后，工具调用返回 "client error: 401 unauthorized"B. 处理措施检查容器网络配置，发现容器 IP 为 172.30.0.2（Docker bridge 网络），而 Nightingale 服务器在 192.168.124.79C. 修复措施修改 docker-compose.yml，将 network_mode 改为 host 模式D. 当前状态仍返回 401 错误，问题根源是 Nightingale 服务器端的配置，需要在 config.toml 中启用 HTTP.TokenAuth.Enable = truesequenceDiagram participant M as mcporter participant C as 配置文件 participant S as n9e-mcp-server participant N as Nightingale API M->>C: 读取配置（错误位置） M->>S: 尝试 stdio 连接 S-->>M: 连接失败 M->>C: 读取配置（正确位置） M->>S: GET /mcp?token=xxx S->>S: 验证 token S-->>M: endpoint 事件 M->>S: POST /mcp?sessionid=XXX Note over S: token 验证拦截（问题） S-->>M: 401 unauthorized Note over S: 修复后：跳过 token 验证 M->>S: POST /mcp?sessionid=XXX S-->>M: SSE 消息 M->>N: 调用 API N-->>M: 401 unauthorized（服务器配置问题）三、问题分析1. 直接原因n9e-mcp-server 的 HTTP 处理器对所有请求强制执行 token 认证，包括已建立 SSE 会话的 POST 请求2. 根本原因（5 Whys 分析）A. 为什么出现这个问题？代码未区分初始连接请求和会话请求，统一要求 token 认证B. 为什么没有及时发现？初始测试使用 GET 请求建立 SSE 连接，这种场景下 token 验证是正确的，问题仅在后续 POST 请求时暴露C. 为什么 SSE 会话请求不需要 token？SSE 协议流程规定：初始 GET 请求使用 token 建立连接服务器返回 endpoint 事件，包含 sessionid后续 POST 请求仅使用 sessionid 作为认证依据D. 为什么容器网络问题会影响 API 调用？Nightingale 服务器配置了 IP 白名单，容器 IP 不在白名单内E. 为什么 401 问题仍未完全解决？这是 Nightingale 服务器端的配置问题，不在 n9e-mcp-server 代码范围内3. 深层反思mcporter 的配置文件位置不符合预期（~/.mcporter/ 而非 ~/.claude/config/）go-sdk 中 SessionID 返回空字符串的注释容易引发误解HTTP 服务器的认证逻辑需要区分不同类型的请求四、解决方案1. 临时方案A. 实施措施无临时方案，问题根因明确，直接进行代码修复2. 永久方案A. 代码层面改进修改 http_server.go，对 POST 请求添加 sessionid 检查，跳过 token 认证B. 配置层面改进更新 mcporter 配置为正确的 HTTP SSE 模式，使用正确的配置文件路径C. 网络层面改进Docker 容器使用 host 网络模式，避免 IP 限制问题3. 预防措施A. 代码审查在代码 Review 时关注认证逻辑的边界条件B. 文档完善明确说明 mcporter 的配置文件位置C. 测试覆盖增加 SSE 会话请求的测试用例五、经验总结1. 做得好的地方通过 curl 测试隔离了问题范围检查 go-sdk 源码确认了 session_id 行为的预期性系统化排查流程，从配置到代码到网络2. 需要改进的地方未尽早确认 mcporter 的配置文件位置对 SSE 协议的认证流程理解不够深入3. 流程优化建议建立 MCP 服务器调试 checklist明确各工具的配置文件位置规范记录常见协议流程（SSE、stdio）的差异点六、参考资料MCP 规范文档go-sdk 源代码Nightingale API 文档
使用 n8n 替代 uptime-kuma 服务监控方案一、概述1. 背景在资源受限的服务器环境中，运行多个 Docker 服务可能会导致内存占用过高。uptime-kuma 是一款流行的网络服务健康检测工具，但其内存占用通常超过 100M。对于只有 2G 内存的小型云服务器来说，这是不小的负担。2. 解决方案使用 n8n 工作流自动化平台，结合 Schedule Trigger（定时触发器）、Data Table（数据表）、邮件通知/飞书通知等组件，完全可以实现 uptime-kuma 的核心功能。核心组件Schedule Trigger：定时执行检测任务Data Table：存储监控目标数据HTTP Request 节点：检测服务可用性Code 节点：检测 SSL 证书状态邮件/飞书通知：异常告警二、数据表设计1. Data Table 结构n8n 自带的 Data Table 可作为简易数据库使用，无需额外维护 Google Sheets 等外部服务。字段说明字段名类型说明namestring服务名称，用于通知时显示urlstring服务地址checkSSLboolean是否检测 SSL 证书状态normalbooleanURL 请求是否正常SSLExpiredbooleanSSL 证书是否过期三、服务可用性检测1. HTTP 状态检测使用 HTTP Request 节点请求目标 URL，通过响应状态码判断服务是否正常。配置要点开启 Response 选项以获取状态码将返回的状态码与预设的 normalCode 进行对比根据对比结果更新 normal 字段graph LR A[定时触发] --> B[读取数据表] B --> C[HTTP Request] C --> D{状态码检查} D -->|正常| E[更新 normal=true] D -->|异常| F[更新 normal=false]四、SSL 证书状态检测1. 初步方案（已废弃）最初尝试使用 ssl-checker.io 网站获取证书信息，但该服务稳定性差，经常返回 504 错误。2. 最终方案使用 Code 节点调用 Node.js 内置的 tls 模块直接获取证书信息。代码实现const tls = require('tls'); const domain = $input.first().json.domain; return new Promise((resolve, reject) => { try { const socket = tls.connect(443, domain, { servername: domain, timeout: 5000 }, () => { const cert = socket.getPeerCertificate(); if (!cert || Object.keys(cert).length === 0) { resolve({ json: { error: "未能获取证书信息" } }); return; } const validTo = new Date(cert.valid_to); const now = new Date(); const daysRemaining = Math.floor((validTo - now) / (1000 * 60 * 60 * 24)); resolve({ json: { domain: domain, issuer: cert.issuer.O, valid_from: cert.valid_from, valid_to: cert.valid_to, days_remaining: daysRemaining, is_valid: daysRemaining > 0, status: daysRemaining < 7 ? "警告：即将过期" : "正常" } }); socket.end(); }); socket.on('error', (err) => { resolve({ json: { domain: domain, error: err.message, status: "连接失败" } }); }); socket.on('timeout', () => { socket.destroy(); resolve({ json: { domain: domain, error: "连接超时", status: "超时" } }); }); } catch (error) { resolve({ json: { error: error.message } }); } });环境配置n8n 默认不允许 Code 节点导入任何模块，需要设置 Docker 环境变量开启内置模块：# 启用 tls 模块 NODE_FUNCTION_ALLOW_BUILTIN=tls设置后重启 Docker 实例即可生效。graph TB A[定时触发] --> B[读取数据表] B --> C{checkSSL?} C -->|是| D[Code 节点: TLS 证书检测] C -->|否| E[跳过] D --> F{剩余天数 < 7?} F -->|是| G[设置 SSLExpired=true] F -->|否| H[设置 SSLExpired=false]五、工作流编排1. 依次间隔触发使用 Data Table 的 get rows 功能获取所有数据后，n8n 默认会并发处理所有 item。为避免并发压力，需要实现依次触发的机制。实现方式采用 Loop Over Items + Wait 节点的组合：Loop 节点遍历所有 itemWait 节点设置延迟时间按 itemIndex 设置递增延迟注意事项Wait 节点的多个延迟时间设置会在第一个延迟到达时同时触发所有 item，这与直觉不符，需通过 Loop 方式实现真正的依次触发。sequenceDiagram participant S as 定时触发器 participant D as Data Table participant L as Loop 节点 participant H as HTTP Request participant C as Code 节点 participant N as 通知节点 S->>D: 获取所有监控项 D->>L: 返回 items 列表 loop 每个 item L->>H: 发送 HTTP 请求 H-->>L: 返回状态码 L->>C: 检查 SSL 证书 C-->>L: 返回证书状态 L->>L: Wait 延迟 end L->>N: 发送异常通知六、通知方案1. 邮件通知n8n 内置发送邮件节点，可配置 SMTP 服务器发送告警邮件。2. 飞书通知（推荐）使用社区节点 n8n-nodes-feishu-lite，该节点包含上百个飞书开放 API 功能。配置步骤在飞书开放平台创建机器人应用获取 Webhook 地址或 App ID、App Secret在 n8n 中安装 n8n-nodes-feishu-lite 节点配置凭证并选择相应的通知类型优势功能丰富，覆盖飞书 API 的各个方面支持 Webhook 类通知可扩展性强3. 其他 Webhook 通知使用 HTTP Request 节点可触发任何基于 Webhook 的推送渠道，如钉钉、企业微信等。graph TB A[检测完成] --> B{状态检查} B -->|服务异常| C[发送告警通知] B -->|证书即将过期| C B -->|证书已过期| C B -->|一切正常| D[结束] C --> E[邮件/飞书/Webhook]七、完整工作流1. 工作流结构整个监控工作流包含以下步骤：Schedule Trigger 定时触发Data Table 获取所有监控目标Loop 遍历每个目标HTTP Request 检测服务可用性Code 节点检测 SSL 证书状态更新 Data Table 状态根据检测结果发送通知graph TB subgraph 触发层 A[Schedule Trigger 定时触发] end subgraph 数据层 B[Data Table 监控目标列表] end subgraph 检测层 C[Loop Over Items 遍历目标] D[HTTP Request 服务可用性] E[Code Node SSL 证书检测] F[Wait 间隔延迟] end subgraph 通知层 G{状态判断} H[邮件通知] I[飞书通知] J[Webhook 通知] end A --> B B --> C C --> D C --> E D --> F E --> F F --> C C --> G G -->|异常| H G -->|异常| I G -->|异常| J八、方案优势1. 资源节约相比 uptime-kuma 占用 100M+ 内存，n8n 方案无需额外部署服务，内存占用更可控。2. 功能灵活可自定义检测逻辑支持多种通知渠道可集成到现有工作流中3. 数据自主使用 n8n 自带 Data Table，数据完全自主可控，无需依赖外部服务。4. 扩展性强基于 n8n 的工作流能力，可轻松扩展更多监控指标和通知方式。参考资料如何使用n8n替代uptime-kuman8n Code 节点模块配置n8n Code 节点内置方法和变量n8n-nodes-feishu-lite GitHub 仓库
DNS 域名系统详解教程一、概述1. 简介A. 是什么DNS（Domain Name System，域名系统）是互联网的核心基础设施，负责将人类可读的域名转换为机器可识别的 IP 地址。当用户在浏览器中输入 example.com 时，DNS 系统会解析出对应的 IP 地址 93.184.216.34，使浏览器能够建立连接。B. 为什么学理解互联网基础设施的工作原理掌握域名解析和故障排查技能优化网站性能和可用性保障电子邮件系统的正常运行C. 学完能做什么配置和管理 DNS 记录排查 DNS 解析问题优化 DNS 传播时间理解负载均衡和高可用架构2. 前置知识A. 必备技能基本 IP 地址概念（IPv4、IPv6）命令行操作基础B. 推荐知识网络基础知识Web 服务器概念二、核心概念1. DNS 层级结构DNS 采用分层架构，类似 referrals 链条。每一层只知道自己下一层的信息，没有单一实体掌握全部信息。graph TD A[Root 根服务器 .] --> B[TLD 顶级域名服务器 .com] A --> C[TLD 顶级域名服务器 .org] A --> D[TLD 顶级域名服务器 .io] B --> E[权威域名服务器 example.com] B --> F[权威域名服务器 google.com] E --> G[子域名 api.example.com] E --> H[子域名 mail.example.com]A. Root（根服务器）全球共有 13 个根服务器集群，由 Verisign、ICANN、NASA 等组织运营。根服务器不直接知道任何域名地址，但知道所有 TLD 服务器的位置，是 DNS 查询的起点。B. TLD（Top Level Domain，顶级域名）域名的最后一部分，如 .com、.org、.io、.dev。TLD 服务器知道其下注册的所有域名。常见 TLD 类型：.com：商业用途，任何人均可注册.org：组织机构.net：网络服务.io：英属印度洋领地（科技行业热门）.dev：开发者（强制 HTTPS）.gov：美国政府专用.edu：教育机构C. Domain（域名）从注册商购买的实际名称，如 example、google、github。与 TLD 组合形成完整域名 example.com。常用注册商包括 Namecheap、GoDaddy、Cloudflare。D. Subdomain（子域名）域名前的任何部分，如 api.example.com、mail.example.com、staging.example.com。子域名可免费无限创建，通过 DNS 记录配置。三、DNS 记录类型1. A 记录将域名映射到 IPv4 地址，是最常用的记录类型。example.com A 93.184.216.34当用户请求 example.com 时，DNS 返回 93.184.216.34。2. AAAA 记录将域名映射到 IPv6 地址。名称源于四个 A（IPv6 地址长度是 IPv4 的四倍）。example.com AAAA 2606:2800:220:1:248:1893:25c8:19463. CNAME（Canonical Name，规范名称）将域名指向另一个域名，而非 IP 地址。常用于第三方服务集成。www.example.com CNAME example.com blog.example.com CNAME example.ghost.io使用场景：将子域名指向托管服务（Ghost、GitBook 等），无需管理其 IP 地址。4. MX（Mail Exchange，邮件交换）指定域名的邮件服务器地址。优先级数字越小，优先级越高。example.com MX 10 mail1.example.com example.com MX 20 mail2.example.com当发送邮件至 hello@example.com 时，邮件服务器查询 MX 记录。若 mail1（优先级 10）不可用，则尝试 mail2（优先级 20）。5. TXT 记录存储文本信息，用于多种验证和安全场景。example.com TXT "v=spf1 include:_spf.google.com ~all" example.com TXT "google-site-verification=abc123xyz"常见用途：域名所有权验证：Google、Stripe、AWS 要求添加 TXT 记录SPF：指定哪些服务器可代表该域名发送邮件（防止伪造）DKIM：使用加密签名进行邮件认证DMARC：定义 SPF/DKIM 检查失败的处理策略四、TTL（Time To Live，生存时间）1. TTL 作用TTL 告诉 DNS 解析器缓存查询结果的时长。example.com A 93.184.216.34 TTL=3600表示：将此结果缓存 3600 秒（1 小时），期间不再重复查询。2. 常见 TTL 值300（5 分钟）：频繁变更，需要快速故障转移3600（1 小时）：普通网站86400（1 天）：极少变更3. 权衡考虑低 TTL：更新更快，但 DNS 查询更多（首次加载稍慢）高 TTL：查询更少（性能更好），但记录变更后传播更慢专业建议：计划服务器迁移时，提前数天将 TTL 降至 300。迁移后，旧的缓存记录 5 分钟内过期，而非数小时。五、DNS 解析流程1. 完整解析过程当用户在浏览器输入 api.example.com 时：sequenceDiagram participant B as 浏览器 participant BC as 浏览器缓存 participant OS as OS缓存 participant R as 路由器缓存 participant ISP as ISP解析器 participant Root as 根服务器 participant TLD as .com TLD服务器 participant NS as example.com权威服务器 B->>BC: 查询 api.example.com BC-->>B: 未找到 B->>OS: 查询 api.example.com OS-->>B: 未找到 B->>R: 查询 api.example.com R-->>B: 未找到 B->>ISP: 查询 api.example.com ISP->>Root: api.example.com 在哪里？ Root-->>ISP: .com TLD 在 192.5.6.30 ISP->>TLD: api.example.com 在哪里？ TLD-->>ISP: example.com 名称服务器在 ns1.example.com ISP->>NS: api.example.com 在哪里？ NS-->>ISP: IP 是 93.184.216.34 ISP-->>B: 返回 93.184.216.34 B->>B: 连接到 93.184.216.34A. 浏览器缓存检查是否缓存了域名解析结果B. OS DNS 缓存操作系统级别的 DNS 缓存C. 路由器缓存家用或企业路由器的 DNS 缓存D. ISP DNS 解析器互联网服务提供商的递归解析器E. 根服务器返回 TLD 服务器地址F. TLD 服务器返回权威域名服务器地址G. 权威域名服务器返回最终 IP 地址H. 响应缓存解析器根据 TTL 缓存结果，后续请求直接返回缓存2. Resolver 与 Nameserver 区别Resolver（解析器）负责递归查询的服务器，代表用户完成 Root → TLD → 权威服务器的完整查询流程。常用公共解析器：8.8.8.8：Google Public DNS1.1.1.1：Cloudflare（最快、注重隐私）208.67.222.222：OpenDNS（Cisco）9.9.9.9：Quad9（注重安全、拦截恶意软件）Nameserver（名称服务器）存储域名实际 DNS 记录的服务器，是域名的权威信息源。注册商提供的默认名称服务器：ns1.namecheap.com ns2.namecheap.com可更改为第三方服务：# Cloudflare ns1.cloudflare.com ns2.cloudflare.com # AWS Route 53（示例） ns-1234.awsdns-56.org ns-789.awsdns-12.co.uk3. Authoritative 与 RecursiveAuthoritative Nameserver（权威名称服务器）拥有域名的最终答案。被询问 example.com 的位置时，直接返回实际 IP 地址。Recursive Resolver（递归解析器）不持有记录，通过询问权威服务器查找答案。ISP DNS 服务器和 8.8.8.8 属于此类。六、DNS 故障排查1. 查看 DNS 缓存浏览器缓存# Chrome chrome://net-internals/#dns # Firefox about:networking#dns # Edge edge://net-internals/#dns显示所有缓存域名及其 IP 和剩余 TTL。操作系统缓存# Windows（命令提示符） ipconfig /displaydns # macOS sudo dscacheutil -cachedump # Linux（使用 systemd-resolved） resolvectl statistics2. 查询域名# 使用 nslookup（Windows/Mac/Linux） nslookup example.com # 使用 dig（Mac/Linux，更详细） dig example.com # 查询特定记录类型 dig example.com MX dig example.com TXT # 使用特定解析器查询 dig @8.8.8.8 example.com dig @1.1.1.1 example.com3. 清除 DNS 缓存浏览器访问 chrome://net-internals/#dns，点击清除主机缓存。操作系统# Windows ipconfig /flushdns # macOS sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder # Linux（systemd） sudo systemd-resolve --flush-caches清除缓存会强制系统重新获取最新的 DNS 记录。七、DNS 在系统设计中的应用1. 负载均衡DNS 可为同一域名返回不同 IP，每次请求可能获得不同服务器。称为 DNS 轮询负载均衡。example.com A 93.184.216.34 example.com A 93.184.216.35 example.com A 93.184.216.362. 故障转移健康检查检测到服务器故障后，DNS 停止返回其 IP，流量自动切换到健康服务器。3. 地理路由返回距离用户最近的服务器 IP。欧洲用户获得欧洲服务器 IP，亚洲用户获得亚洲服务器 IP。称为 GeoDNS 或基于延迟的路由。4. 缓存权衡DNS 缓存减少查询时间和服务器负载，但使即时更新变得不可能。若 TTL 为 24 小时，部分用户可能在 IP 变更后仍访问旧 IP 长达 24 小时。八、快速参考术语功能说明RootDNS 树顶端，知道 TLD 位置TLD.com、.org、.io，知道下属域名Domain购买的域名（example、google）Subdomain免费创建的子域名（api、www、mail）A Record域名 → IPv4 地址AAAA Record域名 → IPv6 地址CNAME域名 → 另一域名（别名）MX邮件发送目标TXT验证、SPF、DKIM、DMARCTTL缓存时长（秒）Resolver查找 IP 的服务器参考资料DNS Explained - How Domain Names Get Resolved | Manish Bhusal
ip2region 离线 IP 地址定位库技术分析一、项目概述1. 简介A. 是什么ip2region 是一个离线 IP 地址定位库和 IP 定位数据管理框架，同时支持 IPv4 和 IPv6，10 微秒级别的查询效率，提供了众多主流编程语言的 xdb 数据生成和查询客户端实现。B. 为什么值得关注极致性能：单次查询响应时间在十微秒级别完全离线：无需外部 API 调用，降低延迟和成本多语言支持：涵盖 Golang、PHP、Java、C、Lua、Rust、Python、JavaScript、Csharp 等主流编程语言数据可控：支持自定义 region 信息，可管理自有 IP 定位数据C. 适用场景用户地理位置统计和分析访问控制和地域限制广告定向投放安全防护和反欺诈离线环境的 IP 定位需求2. 核心特性A. 离线定位库项目提供了一份 IPv4（data/ipv4_source.txt）和 IPv6（data/ipv6_source.txt）的原始数据和对应的 xdb 文件（data/ip2region_v4.xdb 和 data/ip2region_v6.xdb）用于实现精确到城市的查询定位功能。B. 数据管理框架xdb 支持亿级别的 IP 数据段行数，region 信息支持完全自定义。自带数据的 region 信息固定格式为：国家|省份|城市|ISP。可以在 region 中追加特定业务需求的数据，例如 GPS 信息、国际统一地域信息编码、邮编等。C. 数据去重和压缩xdb 格式生成程序会自动处理输入的原始数据，检查并且完成相连 IP 段的合并以及相同地域信息的去重和压缩。二、技术架构1. 系统组成ip2region 由三个核心部分组成：A. 原始数据源IPv4 原始数据：ipv4_source.txtIPv6 原始数据：ipv6_source.txt数据格式：起始 IP、结束 IP、地域信息B. xdb 数据文件二进制格式的高效索引文件支持 IPv4 和 IPv6经过去重和压缩处理C. 查询客户端多语言实现的查询 API统一的查询接口支持内存加速查询2. 工作原理graph TB A[IP 地址输入] --> B[查询客户端] B --> C{xdb 查询引擎} C --> D[Vector Index 缓存] C --> E[XDB 文件] D --> F[内存加速] E --> G[磁盘 IO] F --> H[地域信息] G --> H H --> I[返回结果]3. 查询优化策略A. vIndex 索引缓存使用固定的 512KiB 的内存空间缓存 vector index 数据，减少一次 IO 磁盘操作，保持平均查询效率稳定在 100 微秒之内。B. xdb 整个文件缓存将整个 xdb 文件全部加载到内存，内存占用等同于 xdb 文件大小，无磁盘 IO 操作，保持 10 微秒级别的查询效率。graph LR A[查询策略] --> B[vIndex 缓存] A --> C[文件缓存] B --> D[512KiB 内存] B --> E[100 微秒级] C --> F[xdb 文件大小] C --> G[10 微秒级]三、xdb 数据结构1. 数据格式设计xdb 格式是 ip2region 的核心创新，通过精巧的数据结构设计实现了极高效的查询性能。A. 存储结构Vector Index：向量索引，用于快速定位数据块Data Segment：数据段，存储 IP 范围和地域信息Region Info：地域信息，采用压缩存储B. 查询流程sequenceDiagram participant C as 客户端 participant V as Vector Index participant S as Data Segment participant R as Region Info C->>V: 输入 IP 地址 V->>V: 计算 IP 索引 V->>S: 定位数据段 S->>R: 读取地域信息 R-->>C: 返回定位结果2. 数据生成流程A. 输入数据处理读取原始 IP 数据验证数据格式合并连续 IP 段B. 去重和压缩相同地域信息去重IP 段合并优化区域信息压缩C. 索引构建生成 Vector Index构建 Data Segment写入 xdb 文件四、多语言支持1. 查询客户端实现ip2region 提供了丰富的编程语言绑定，覆盖了主流的开发场景：编程语言描述IPv4 支持IPv6 支持Golanggolang xdb 查询客户端支持支持PHPphp xdb 查询客户端支持支持Javajava xdb 查询客户端支持支持CPOSIX C xdb 查询客户端支持支持Lua_clua c 扩展 xdb 查询客户端支持支持Lualua xdb 查询客户端支持支持Rustrust xdb 查询客户端支持支持Pythonpython xdb 查询客户端支持支持Javascriptjavascript xdb 查询客户端支持支持Csharpcsharp xdb 查询客户端支持支持Erlangerlang xdb 查询客户端支持不支持Nginxnginx 扩展 xdb 查询客户端支持不支持C++C++ xdb 查询客户端支持支持2. 数据生成工具编程语言描述IPv4 支持IPv6 支持Golanggolang xdb 生成程序支持支持Javajava xdb 生成程序支持支持Pythonpython xdb 生成程序支持不支持Csharpcsharp xdb 生成程序支持不支持Rustrust xdb 生成程序支持支持C++C++ xdb 生成程序支持支持五、使用示例1. Python 查询示例from xdbSearcher import XdbSearcher # 创建查询对象 db_path = "ip2region.xdb" searcher = XdbSearcher(db_path) # 查询 IP 地址 ip = "202.96.128.86" region = searcher.search(ip) print(region) # 输出：中国|0|上海|电信 # 使用缓存加速 searcher_with_cache = XdbSearcher(db_path, vector_index=True) region = searcher_with_cache.search(ip) # 关闭查询对象 searcher.close()2. Golang 查询示例package main import ( "fmt" "github.com/lionsoul2014/ip2region/xdb" ) func main() { // 创建查询对象 searcher, err := xdb.New("./ip2region.xdb") if err != nil { panic(err) } defer searcher.Close() // 查询 IP 地址 ip := "202.96.128.86" region, err := searcher.SearchByStr(ip) if err != nil { panic(err) } fmt.Println(region) // 输出：中国|0|上海|电信 }六、数据更新机制1. 数据源管理ip2region 项目的核心在于研究 IP 数据的存储和快速查询的设计和实现，项目自带的原始数据不会再提供更新。A. 数据源获取途径ip2region 社区提供的数据（关注官方公众号）ip2region Github/Gitee 中带有数据源补充标签的 Issue其他自定义数据：客户提供的数据、GPS 和 WIFI 定位数据、其他平台的合法合规数据B. 手动编辑更新基于 ip2region 自带的原始 IP 数据，使用提供的编辑工具来修改数据。编程语言描述IPv4 支持IPv6 支持Golanggolang IP 原始数据编辑器支持支持Javajava IP 原始数据编辑器支持不支持C++C++ IP 原始数据编辑器支持支持2. 自动更新机制如果通过自己的 API 或数据源来更新数据，可以参考基于检测算法的更新算法来编写更新程序。七、性能分析1. 查询性能指标基于文件的查询：十微秒级别vIndex 缓存查询：100 微秒级别全文件内存缓存：10 微秒级别2. 内存占用vIndex 缓存模式：固定 512KiB全文件缓存模式：等同于 xdb 文件大小（通常数 MB 到数十 MB）3. 并发安全xdb 格式设计支持并发安全查询，读操作无需加锁。八、应用场景1. Web 应用用户访问统计和分析地域化内容展示访问控制和限制2. 移动应用位置服务增强内容推荐优化用户行为分析3. 网络安全异常访问检测地域欺诈防护访问来源追踪九、社区生态1. 官方社区Ip2Region 官方社区于 2025 年 6 月 12 日正式上线，提供稳定的商用离线数据服务。A. 社区服务商用离线数据服务使用文档和查询测试数据纠错和反馈B. 技术支持微信公众号：lionsoul-orgGitHub 仓库：lionsoul2014/ip2region官方社区网站2. 技术文档项目提供了丰富的技术文档，包括：xdb 数据结构分析xdb 查询过程分析xdb 生成过程分析xdb 文件生成教程xdb 并发安全查询xdb 数据更新方法十、技术特点总结1. 核心优势极致性能：10 微秒级查询响应完全离线：无外部依赖多语言支持：覆盖主流编程语言数据可控：支持自定义地域信息2. 技术创新xdb 数据格式：高效的数据结构和索引设计内存优化：灵活的缓存策略数据压缩：智能的 IP 段合并和去重3. 适用性高并发场景：并发安全查询低延迟要求：微秒级响应离线环境：无需网络连接多语言项目：跨平台支持参考资料ip2region GitHub 仓库