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
服务器硬件传感器监控部署实战一、概述1. 简介A. 是什么硬件传感器监控是通过 lm-sensors 工具采集服务器硬件数据，包括 CPU 温度、风扇转速、电压等信息，并通过 Categraf 采集上报到监控系统的解决方案。B. 为什么需要及时发现硬件异常，如温度过高、风扇故障预防性维护，避免硬件损坏导致服务中断建立硬件性能基线，辅助容量规划C. 实现目标监控 CPU 温度（Package 和各核心）监控风扇转速（RPM）输出 Prometheus 格式指标，接入夜莺监控系统2. 环境信息A. 目标服务器192.168.86.153（已部署）192.168.86.152（已部署）B. 基础环境操作系统：Ubuntu 22.04Categraf 目录：/opt/categraf/conf/input.exec/Python 版本：3.10+二、技术方案1. 架构设计graph LR A[lm-sensors] -->|sensors -j| B[Python监控脚本] B -->|Prometheus格式| C[Categraf exec插件] C -->|上报| D[夜莺监控系统]2. 技术选型A. 数据采集：lm-sensors + jqsensors 命令支持 -j 参数输出 JSON 格式jq 工具用于后续可能的 JSON 处理B. 脚本语言：Python 3执行效率高（0.1秒内完成）JSON 处理方便异常处理完善C. 上报方式：Categraf exec 插件支持 Prometheus 格式解析与现有监控体系无缝集成三、部署步骤1. 安装依赖A. 安装 jqapt-get update && apt-get install -y jqB. 验证依赖sensors --version python3 --version jq --version2. 部署监控脚本A. 创建脚本文件将以下内容保存到 /opt/categraf/conf/input.exec/sensors_monitor.py：#!/usr/bin/env python3 import subprocess import json import re import sys _SENSOR_PATTERN = re.compile(r"^(temp|fan)(d+)_(.+)$") def sanitize_label(s: str) -> str: s = s.replace("\\", "\\\\").replace('"', '\\"') s = re.sub(r"[^a-zA-Z0-9_]", "_", s) return s.strip("_") def get_metric_info(key: str) -> tuple: m = _SENSOR_PATTERN.match(key) if not m: return None, None t, suffix = m.group(1), m.group(3) if t == "temp": mapping = { "input": ("hw_temperature_celsius", "input"), "max": ("hw_temperature_max_celsius", "max"), "crit": ("hw_temperature_crit_celsius", "crit"), "alarm": ("hw_sensor_alarm", "alarm"), } else: mapping = { "input": ("hw_fan_rpm", "input"), "min": ("hw_fan_min_rpm", "min"), "max": ("hw_fan_max_rpm", "max"), } return mapping.get(suffix, (None, None)) def format_value(v) -> str: if isinstance(v, (int, float)): if v == 0: return "0" if 0.001 <= abs(v) < 10000: s = f"{v:.6g}" if "." in s: s = s.rstrip("0").rstrip(".") return s return f"{v:.6g}" return str(v) def main() -> None: try: data = json.loads(subprocess.check_output(["sensors", "-j"], timeout=5, text=True)) for chip, chip_data in data.items(): chip_safe = sanitize_label(chip) for sensor, sensor_data in chip_data.items(): if sensor == "Adapter": continue sensor_safe = sanitize_label(sensor) for key, value in sensor_data.items(): if value is None: continue metric, suffix = get_metric_info(key) if not metric: continue if suffix == "alarm" and value == 0: continue labels = f'chip="{chip_safe}",sensor="{sensor_safe}"' if suffix == "alarm": labels += ',type="temperature"' print(f"{metric}{{{labels}}} {format_value(value)}") except subprocess.TimeoutExpired: sys.stderr.write("Error: sensors command timed out\n") sys.exit(1) except json.JSONDecodeError as e: sys.stderr.write(f"Error: Invalid JSON output: {e}\n") sys.exit(1) except OSError as e: sys.stderr.write(f"Error: Failed to run sensors: {e}\n") sys.exit(1) except Exception as e: sys.stderr.write(f"Unexpected error: {e}\n") sys.exit(1) if __name__ == "__main__": main()B. 设置执行权限chmod +x /opt/categraf/conf/input.exec/sensors_monitor.py3. 配置 CategrafA. 编辑 exec.tomlvi /opt/categraf/conf/input.exec/exec.toml配置内容：# 传感器监控配置 - Categraf exec 插件 instances commands = [ "/opt/categraf/conf/input.exec/sensors_monitor.py" ] data_format = "prometheus" timeout = "10s"B. 重启 Categrafsystemctl restart categraf systemctl status categraf四、脚本说明1. 核心功能A. 数据采集调用 sensors -j 获取 JSON 格式传感器数据超时时间设置为 5 秒B. 数据处理自动识别芯片和传感器类型清理标签中的特殊字符格式化数值输出C. 指标输出指标名称说明标签hw_temperature_celsius当前温度chip, sensorhw_temperature_max_celsius温度上限chip, sensorhw_temperature_crit_celsius温度临界值chip, sensorhw_sensor_alarm温度告警状态chip, sensor, typehw_fan_rpm风扇转速chip, sensorhw_fan_min_rpm风扇最低转速chip, sensorhw_fan_max_rpm风扇最高转速chip, sensor2. 代码优化要点A. 性能优化预编译正则表达式，避免重复编译单次 JSON 解析处理所有数据执行时间控制在 0.1 秒以内B. 安全性标签值中的引号和反斜杠进行转义避免标签注入导致的格式错误C. 异常处理超时异常：命令执行超时JSON 解析异常：输出格式错误操作系统异常：sensors 命令不可用五、输出示例1. CPU 温度指标hw_temperature_celsius{chip="coretemp_isa_0000",sensor="Package_id_0"} 48 hw_temperature_max_celsius{chip="coretemp_isa_0000",sensor="Package_id_0"} 79 hw_temperature_crit_celsius{chip="coretemp_isa_0000",sensor="Package_id_0"} 99 hw_temperature_celsius{chip="coretemp_isa_0000",sensor="Core_0"} 45 hw_temperature_max_celsius{chip="coretemp_isa_0000",sensor="Core_0"} 792. 风扇转速指标hw_fan_rpm{chip="applesmc_isa_0300",sensor="Main"} 1002 hw_fan_min_rpm{chip="applesmc_isa_0300",sensor="Main"} 1000 hw_fan_max_rpm{chip="applesmc_isa_0300",sensor="Main"} 1900六、验证测试1. 本地测试脚本/opt/categraf/conf/input.exec/sensors_monitor.py预期输出：Prometheus 格式的指标数据，约 140-146 行2. 检查服务状态systemctl status categraf journalctl -u categraf -n 50 --no-pager3. 验证数据上报在夜莺监控系统中查询 hw_temperature_celsius 和 hw_fan_rpm 指标七、常见问题1. 执行超时问题描述脚本执行超过 10 秒，Categraf 报错解决方案检查传感器数量，过多设备可能需要优化增加超时时间配置2. 格式解析错误问题描述Categraf 报错：expected float as value, got ""解决方案检查 format_value 函数对 0 值的处理确保所有数值都有输出3. 依赖缺失问题描述Error: sensors not found 或 Error: jq not found解决方案apt-get install lm-sensors jq八、部署结果1. 服务器状态服务器jq 版本PythonCategraf指标数状态192.168.86.1531.6-2.1ubuntu3.13.10运行中146正常192.168.86.1521.6-2.1ubuntu3.13.10运行中140正常2. 监控指标CPU 温度监控：Package + 14 个核心风扇转速监控：主风扇温度阈值：max 79°C、crit 99°C风扇阈值：min 1000 RPM、max 1900 RPM参考资料lm-sensors 官方文档Categraf 官方文档Prometheus 数据格式
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 文档
.online 域名被封禁引发的死循环故障复盘
.online 域名被封禁引发的死循环故障复盘一、事件概述1. 事件背景作者在 Namecheap 的促销活动中免费获得了一个 .online 顶级域名，用于托管一个小型浏览器项目。几周后发现该域名完全无法访问，被标记为不安全网站。2. 影响范围A. 影响用户数项目刚上线，用户量极小，实际影响有限B. 影响时长从发现到最终解决，持续数小时（文章发布后 40 分钟内得到解决）C. 影响功能整个网站无法访问，DNS 解析完全失效3. 严重程度P3 级故障（非核心业务，但域名完全无法使用）二、事件时间线1. 故障发生（时间：不明）A. 现象描述域名突然无法解析，访问时显示全屏红色警告"这是一个不安全的网站"B. 监控告警无监控告警，作者是在检查其他域名流量数据时偶然发现2. 问题发现（时间：几周后）A. 发现途径查看流量数据时发现过去 48 小时零访问量B. 初步判断可能是域名被标记或挂起3. 排查过程A. 检查 CloudflareCloudflare 仍正常激活，Worker 指向正确B. 检查注册商域名在 Namecheap 账户中正常显示，过期日期正确，域名服务器配置正确C. DNS 查询dig NS getwisp.online +short返回为空，解析完全失败D. WHOIS 查询状态显示：serverHold4. 深入调查A. 联系注册商Namecheap 回复：域名是由注册局（registry）挂起的，不是他们。注册局通常因为域名涉及滥用操作而挂起域名。B. 联系注册局 RadixRadix 回复：域名因在 Google Safe Browsing 黑名单上而被暂停。需要按照列表页面上的说明申请移除。sequenceDiagram participant U as 用户 participant N as Namecheap participant R as Radix(注册局) participant G as Google U->>N: 发现域名无法访问 N->>U: 域名由注册局挂起 U->>R: 询问挂起原因 R->>U: 因Google黑名单而暂停 U->>G: 申请移除黑名单 G->>U: 需验证域名所有权 U->>U: 无法验证（域名不解析） Note over U,G: 死循环5. 解决尝试A. Google Safe Bleaning 报告在多个渠道提交误报报告，但无进展B. Google Search Console需要通过 DNS TXT 或 CNAME 记录验证域名所有权，但域名不解析无法添加记录C. Safe Search 团队审核提交审核请求，但收到"未提交有效页面"的错误D. 注册局临时释放向注册局申请临时释放以便 Google 审核内容6. 最终解决A. HN 发布将故事发布到 Hacker NewsB. Google 响应发布后 40 分钟内，域名从 Google Safe Search 黑名单中移除C. 域名恢复域名恢复正常访问三、问题分析1. 直接原因域名被 Google Safe Browsing 误标记为不安全网站，注册局 Radix 据此暂停了域名2. 根本原因（5 Whys 分析）A. 为什么域名被标记？原因不明，可能是有人恶意举报或算法误判B. 为什么注册局立即暂停？Radix 对 .online 等新顶级域名采取"零容忍"策略，一旦被标记立即暂停C. 为什么无法解除？Google 要求验证域名所有权才能审核，但域名暂停无法解析，形成死循环D. 为什么没有通知？注册商和注册局都没有发送任何通知邮件E. 为什么没有监控？作者没有添加域名到 Google Search Console，也没有配置监控3. 深层反思新顶级域名的注册机制存在严重缺陷Google 和注册局的审核流程缺乏沟通机制用户在域名管理上的疏忽加剧了问题四、解决方案1. 临时方案A. 社区发声在 Hacker News 等社区发布经历，引起关注B. 多渠道申诉向 Google Safe Browsing、Safe Search 多个渠道提交申诉2. 永久方案A. 避免 .online 域名回归 .com 黄金标准，不再使用新顶级域名B. 立即验证新域名注册后立即添加到 Google Search ConsoleC. 监控告警配置域名监控和可用性告警3. 预防措施注册新域名后立即配置所有必要的验证和监控选择可靠的注册商和顶级域名定期检查域名状态graph TB A[注册新域名] --> B[选择可靠TLD] B --> C[立即添加到GSC] C --> D[配置DNS验证] D --> E[设置监控告警] E --> F[定期检查状态]五、经验总结1. 做得好的地方彻底排查了问题根源尝试了多种解决途径通过社区发声最终解决问题2. 需要改进的地方使用了非标准顶级域名没有及时添加到 Google Search Console没有配置监控告警3. 流程优化建议建立域名管理 checklist，包括：选择 TLD、验证所有权、配置监控、定期检查4. 技术术语说明serverHold：由注册局设置的域名暂停状态，通常表示严重问题clientHold：由注册商设置的域名暂停状态，通常与付款或账单相关Safe Browsing：Google 的安全浏览功能，用于标记恶意网站Safe Search：Google 的安全搜索功能，用于过滤不当内容六、各方责任分析1. 注册商 Namecheap负责程度：低问题：没有发送通知改进：应在域名状态变化时通知用户2. 注册局 Radix负责程度：高问题：缺乏审核机制，直接暂停域名改进：应提供暂停前的审核机会和通知3. Google负任程度：高问题：审核流程存在死循环改进：域名不解析时应提供替代验证方式参考资料Never Buy A .online Domain | Sid's Blog
DragonflyDB 新型内存数据库架构分析一、背景与目标1. 项目背景A. 业务场景随着云计算和现代应用工作负载的演进，传统内存数据库如 Redis 和 Memcached 在处理大规模数据时面临性能瓶颈。这些传统系统大多基于十年前的设计理念，无法充分利用现代多核 CPU 和大内存服务器的硬件能力。B. 痛点分析传统内存数据库存在以下核心问题：单线程架构限制：Redis 采用单线程模型，无法充分利用多核 CPU内存效率低下：传统缓存算法（LRU、LFU）需要额外的元数据追踪，增加内存开销快照开销巨大：fork 机制导致内存占用激增，影响生产环境稳定性锁竞争严重：多线程扩展面临严重的 mutex 和 spinlock 竞争问题2. 设计目标A. 功能目标完全兼容 Redis 和 Memcached API支持约 185 个 Redis 命令（相当于 Redis 5.0 API）支持所有 Memcached 命令（除 cas 外）B. 非功能目标性能指标：相比传统方案提升 25 倍吞吐量资源效率：在相同工作负载下节省 80% 的服务器资源延迟保证：保持亚毫秒级延迟，99.9% 分位延迟控制在 1-2ms内存效率：快照期间无内存激增，空闲时节省 30% 内存二、核心问题分析1. 问题本质传统内存数据库的性能瓶颈源于三个根本性设计缺陷：A. 无法充分利用现代硬件现代云服务器提供数十个 CPU 核心和数百 GB 内存，但单线程架构只能利用单个核心，造成资源浪费。B. 过时的锁机制传统的 mutex 和 spinlock 机制在高并发场景下导致严重的线程竞争，随着线程数增加，性能反而下降。C. 低效的数据结构传统哈希表和缓存算法设计未考虑现代 CPU 缓存层次结构和内存访问模式。2. 系统组成元素A. 核心概念共享无感架构：各线程独立管理自己的数据分片，无需共享状态分片（Shard）：键空间被划分为多个独立区域，每个区域由单个线程管理VLL 锁管理：基于学术研究的新型事务框架，无需传统锁即可保证原子性Dashtable：基于 Dash 论文的高效哈希表设计B. 组件关系graph TB subgraph "客户端层" Client[客户端应用] end subgraph "协议层" RESP[Redis 协议] MC[Memcached 协议] HTTP[HTTP 控制台] end subgraph "路由层" Router[一致性路由器] end subgraph "执行层" S1[分片 1 线程 1] S2[分片 2 线程 2] S3[分片 N 线程 N] end subgraph "存储层" DT1[Dashtable 1] DT2[Dashtable 2] DTN[Dashtable N] end Client --> RESP Client --> MC Client --> HTTP RESP --> Router MC --> Router Router --> S1 Router --> S2 Router --> S3 S1 --> DT1 S2 --> DT2 S3 --> DTN三、总体设计1. 设计原则A. 共享无感架构将键空间分区为多个分片，每个分片由独立线程管理，线程间无需共享状态或同步锁。B. 学术研究驱动基于两篇重要学术论文：VLL（锁管理器重设计）：实现无锁多键原子操作Dash（可扩展哈希）：构建高效的持久化内存哈希表C. 向后兼容完全兼容 Redis 和 Memcached API，用户无需修改代码即可迁移。2. 系统架构graph LR subgraph "传统 Redis 架构" TR1[客户端 1] --> TRC[单线程 Redis 核心] TR2[客户端 2] --> TRC TR3[客户端 N] --> TRC TRC --> TRL[全局锁] TRC --> TRM[(单一字典)] end subgraph "DragonflyDB 架构" DR1[客户端 1] --> DR[一致性哈希路由] DR2[客户端 2] --> DR DR3[客户端 N] --> DR DR --> D1[分片 1 独立线程] DR --> D2[分片 2 独立线程] DR --> DN[分片 N 独立线程] D1 --> DM1[(本地字典 1)] D2 --> DM2[(本地字典 2)] DN --> DMN[(本地字典 N)] end3. 关键创新A. 无锁原子操作通过 VLL 技术实现多键操作的原子性保证，无需使用 mutex 或 spinlock。B. 自适应缓存算法统一的缓存算法，比 LRU/LFU 实现更高的缓存命中率，且零内存开销。C. 无 Fork 快照创新的快照算法，不需要 fork 进程，避免快照期间内存激增。四、详细设计1. 核心模块A. 共享无感执行引擎基于 fbnc 库实现线程和 I/O 管理，每个线程独立管理自己的分片。B. Dashtable 存储引擎基于 Dash 论文的哈希表实现，具有以下特性：支持增量哈希（数据存储增长期间）支持无状态扫描操作更高的 CPU 和内存效率C. 事务框架基于 VLL 论文实现，支持：多键原子操作无锁并发控制ACID 保证2. 关键流程A. 正常请求处理流程sequenceDiagram participant C as 客户端 participant R as 协议路由器 participant S as 分片线程 participant D as Dashtable C->>R: 发送命令（GET/SET/等） R->>R: 识别协议类型 （RESP/Memcached/HTTP） R->>R: 计算键的分片 R->>S: 转发到对应分片线程 S->>D: 执行操作 D-->>S: 返回结果 S-->>R: 返回结果 R-->>C: 返回响应B. 快照流程sequenceDiagram participant M as 主线程 participant S1 as 分片线程 1 participant S2 as 分片线程 2 participant SN as 分片线程 N participant F as 快照文件 M->>S1: 触发快照请求 M->>S2: 触发快照请求 M->>SN: 触发快照请求 S1->>F: 写入分片 1 数据 S2->>F: 写入分片 2 数据 SN->>F: 写入分片 N 数据 S1-->>M: 完成 S2-->>M: 完成 SN-->>M: 完成 M-->>M: 快照完成 (无需 fork，无内存激增)3. 数据存储A. 存储选型采用自主设计的 Dashtable，而非传统 Redis 字典。B. 数据模型键值对存储支持多种数据结构（String、Hash、List、Set、Sorted Set 等）支持过期时间（TTL）C. 缓存策略单一自适应缓存算法，根据访问模式自动调整驱逐策略。五、性能基准测试1. 测试环境AWS 实例：m5.large、m5.xlarge、c6gn.16xlarge测试工具：memtier_benchmark测试参数：-c 20 -t -d 256 --distinct-client-seed2. 性能对比A. 与 Redis 对比（c6gn.16xlarge）操作Dragonfly QPSRedis QPS性能提升SET3,844K155K25 倍GET3,717K148K25 倍SETEX~3,500K~140K25 倍B. 延迟对比操作P99 延迟P99.9 延迟SET0.8-1ms2.4msGET0.8-0.9ms2.4msSETEX0.9-1.3ms2.4-3.2msC. 与 Memcached 对比操作Dragonfly QPSMemcached QPS优势SET3,844K806K4.8 倍GET3,717K2,100K1.8 倍3. 内存效率A. 快照期间内存对比Dragonfly：快照期间内存无明显增长Redis：快照期间内存增长至 Dragonfly 的 3 倍B. 空闲状态内存对比Dragonfly：基准内存占用Redis：比 Dragonfly 高 30%graph TB title["内存使用对比（5GB 数据）"] idle["空闲状态: Redis 比 Dragonfly 高 30%"] peak["快照峰值: Redis 是 Dragonfly 的 3 倍"] snaptime["快照时间: Dragonfly 仅需数秒"] title --> idle title --> peak title --> snaptime六、技术特性1. 协议兼容性A. Redis 协议支持约 185 个 Redis 命令相当于 Redis 5.0 API 覆盖无需代码修改即可迁移B. Memcached 协议支持所有 Memcached 命令（除 cas 外）可通过 --memcached_port 单独启用C. HTTP 控制台默认通过主 TCP 端口（6379）提供 HTTP 访问自动识别协议类型支持 Prometheus 兼容指标（/metrics 端点）2. 配置选项A. Redis 兼容参数port：连接端口（默认 6379）bind：绑定地址requirepass：认证密码maxmemory：最大内存限制dbfilename：快照文件名B. Dragonfly 特有参数memcached_port：Memcached 协议端口cache_mode：启用自适应缓存keys_output_limit：KEYS 命令返回限制hz：过期检查频率snapshot_cron：自动快照计划3. 监控与运维A. Prometheus 集成默认导出指标到 :6379/metrics兼容 Grafana 仪表板B. HTTP 控制台实时查看数据库状态调试和管理功能C. 自动快照支持 cron 表达式配置粒度精确到分钟七、应用场景1. 适用场景A. 高吞吐量缓存Web 应用会话存储API 响应缓存数据库查询缓存B. 实时数据处理消息队列中间件实时分析系统排行榜和计数器C. 成本敏感场景云环境资源优化容器化部署边缘计算节点2. 迁移路径A. 无缝迁移保持现有 Redis/Memcached 客户端代码不变修改连接地址指向 Dragonfly逐个验证命令兼容性监控性能和资源使用B. 渐进式迁移双写 Redis 和 Dragonfly逐步切换读流量验证稳定性后完全切换八、技术趋势与影响1. 行业影响A. 推动内存数据库现代化Dragonfly 证明了基于现代硬件重新设计内存数据库的可行性。B. 促成新架构模式共享无感架构为其他高性能系统提供了设计参考。C. 降低基础设施成本25 倍性能提升和 80% 资源节省意味着显著的成本降低。2. 技术演进方向A. 当前路线图完善复制 API（Dragonfly 原生复制）支持 Redis 3-6 版本的更多命令优化分布式日志格式B. 长期目标构建云原生内存数据库充分利用硬件加速（如持久化内存）自动化分片和集群管理九、总结Dragonfly 代表了内存数据库设计的一次重要创新。通过基于现代硬件重新思考架构设计，采用共享无感架构、学术研究驱动的高效数据结构，以及创新的缓存和快照算法，Dragonfly 在保持与 Redis 和 Memcached API 兼容的同时，实现了 25 倍的性能提升和 80% 的资源节省。对于寻求高性能、低成本内存数据库解决方案的团队来说，Dragonfly 提供了一个极具吸引力的选择，特别是对于云原生应用和成本敏感场景。参考资料DragonflyDB GitHub 仓库DragonflyDB 官方网站VLL: Lock Manager Redesign for Main Memory Database SystemsDash: Scalable Hashing on Persistent Memory