性能监控与告警系统实战:从0到可观测性的完整技术路线
性能监控与告警系统实战从0到可观测性的完整技术路线性能监控的三个核心层次独立开发者的产品有了真实用户后系统还活着吗就不应该是靠用户投诉来发现的。你需要一套性能监控与告警系统。我把它分为三个层次对应不同的工程成熟度和产品规模L1基础监控Infrastructure Monitoring服务器的CPU、内存、磁盘、网络。数据库的连接数、查询性能。以及应用进程是否还运行。这是让系统在用户投诉之前就被修复的基础。L2应用性能监控Application Performance Monitoring, APM不只是系统还活着而是系统运行得怎么样。API响应时间、错误率、数据库慢查询、外部API调用延迟。这是在用户体验恶化之前发现问题的关键。L3业务指标监控Business Metrics Monitoring系统和应用都健康但业务还健康吗。新用户注册量突然下降、付费转化率突然降低、核心功能的使用率突然下滑。这是在业务出问题之前发现趋势的核心。L1实战Prometheus Grafana的基础监控搭建为什么选Prometheus Grafana这两个工具的组合是开源监控领域的事实标准。Prometheus负责采集和存储指标Grafana负责可视化指标和配置告警。核心概念指标Metric一个可时间序列化的测量值。如cpu_usage_percent、memory_usage_bytes、http_requests_total。采集ScrapingPrometheus定期如每15秒从配置的采集目标Targets拉取指标数据。存储StoragePrometheus用自研的时序数据库TSDB存储指标数据。默认保留15天可配置。实战搭建以监控一个Node.js应用为例第一步让应用暴露指标给Prometheus用prom-client库Node.js生态最流行的Prometheus客户端库// metrics.ts import client from prom-client; // 创建一个Registry指标注册表 const register new client.Registry(); // 1. 默认的系统指标如CPU、内存、事件循环延迟 client.collectDefaultMetrics({ register }); // 2. 自定义指标HTTP请求_duration直方图 const httpRequestDuration new client.Histogram({ name: http_request_duration_seconds, help: Duration of HTTP requests in seconds, labelNames: [method, route, status_code], buckets: [0.1, 0.5, 1, 2, 5] // 响应时间的分桶 }); register.registerMetric(httpRequestDuration); // 3. 写一个/metrics端点返回Prometheus格式的指标 app.get(/metrics, async (req, res) { try { const metrics await register.metrics(); res.set(Content-Type, register.contentType); res.send(metrics); } catch (error) { res.status(500).end(error); } }); // 4. 在中间件里记录每个请求的响应时间 app.use((req, res, next) { const startTime Date.now(); res.on(finish, () { const duration (Date.now() - startTime) / 1000; httpRequestDuration .labels(req.method, req.route?.path || req.path, res.statusCode.toString()) .observe(duration); }); next(); });第二步配置Prometheus来采集这个/metrics端点创建prometheus.yml配置文件global: scrape_interval: 15s # 每15秒采集一次 scrape_configs: - job_name: my-nodejs-app static_configs: - targets: [localhost:3000] # 你的应用的地址运行Prometheus用Dockerdocker run -d \ --nameprometheus \ -p 9090:9090 \ -v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml \ prom/prometheus现在访问http://localhost:9090在Graph页面里输入rate(http_request_duration_seconds_count[5m])就能看到过去5分钟内每秒HTTP请求数的变化。第三步用Grafana可视化这些指标运行Grafana用Dockerdocker run -d \ --namegrafana \ -p 3000:3000 \ grafana/grafana访问http://localhost:3000默认用户名/密码admin/admin。在Grafana里添加Prometheus作为数据源Data Source。导入现成的Node.js应用监控仪表盘Grafana官网有社区贡献的仪表盘JSON可以直接导入。L2实战用Sentry做应用性能监控APMPrometheus Grafana擅长监控系统级指标CPU、内存、请求率。但应用内部发生了什么——哪个SQL查询最慢哪个外部API调用延迟最高用户的一次请求在服务器端花了多长时间——这些需要专门的APM工具。为什么选Sentry它也提供APM功能我已经用Sentry做错误追踪前面文章写过。Sentry从2023年开始也提供了Performance模块——自动追踪应用性能且和错误追踪深度集成这个慢请求有没有关联的错误。核心概念分布式追踪Distributed Tracing现代应用通常不是一个函数处理一个请求。一个请求可能经过负载均衡器 → API服务器 → 数据库 → 外部API如Claude API。分布式追踪给每个请求分配一个唯一的trace_id然后在请求经过的每个服务里记录这个服务花了多长时间处理这叫一个span。最后把这些span在时间轴上连起来就能看到用户请求 → 数据库查询50ms→ AI API调用2000ms→ 返回响应的完整时间线。在Node.js应用里启用Sentry Performance// sentry.ts import * as Sentry from sentry/node; import { Elysium } from sentry/tracing; Sentry.init({ dsn: your-sentry-dsn, environment: process.env.NODE_ENV, tracesSampleRate: 1.0, // 采集100%的请求生产环境可以降到0.1-0.2 integrations: [ new Elysium({ additionalOptions: { trackLayers: true } }), ], }); // 在应用入口处初始化 app.use(Sentry.Handlers.requestHandler()); app.use(Sentry.Handlers.tracingHandler()); // 在应用出口处错误处理之前 app.use(Sentry.Handlers.errorHandler()); app.use(Sentry.Handlers.tracingHandler());启用后Sentry会自动追踪每个HTTP请求的响应时间每个数据库查询的执行时间如果用的是受支持的ORM如Prisma、TypeORM每个外部HTTP调用的耗时如fetch()或axios在Sentry后台查看Performance登录Sentry后台进入Performance页面。你会看到一个Transaction Summary事务摘要列表。每个Transaction对应一个被追踪的操作如一个HTTP请求、一个数据库查询。点击一个慢事务可以看到它的Trace Details追踪详情——一个时间轴展示这个事务所包含的所有span如POST /api/generate → prisma.query → fetch(https://api.anthropic.com)。实战价值找到性能瓶颈2024年8月我通过Sentry Performance发现我的产品的AI生成功能平均响应时间是8秒。但AI API的调用本身只需要5秒。那剩下的3秒花在哪里了查看追踪详情后发现在调用AI API之前我的代码做了一次检查用户订阅状态的数据库查询但这个查询没有加索引导致每次都全表扫描300ms。给这个字段加上索引后查询时间降到了5ms。总响应时间从8秒降到了5.5秒。L3实战业务指标监控的技术实现业务指标如每日新注册用户数、付费转化率通常不是技术指标而是产品指标。但它们对产品的健康度同样重要甚至更重要。为什么不能直接用Google AnalyticsGoogle AnalyticsGA是做网站流量分析的利器。但它有两个局限它追踪的是前端事件如页面浏览、按钮点击。后端发生的业务事件如用户订阅了Pro计划很难用GA准确追踪。它的数据更新有延迟通常24-48小时。你不能在GA里实时看到过去1小时的注册量。我的方案把业务指标存在PostgreSQL里用Grafana做实时仪表盘。第一步设计业务指标的数据表-- 每日指标汇总表用PostgreSQL的物化视图或定时任务填充 CREATE TABLE daily_business_metrics ( id SERIAL PRIMARY KEY, date DATE NOT NULL, new_registrations INTEGER DEFAULT 0, pro_subscriptions INTEGER DEFAULT 0, churn_count INTEGER DEFAULT 0, active_users INTEGER DEFAULT 0, created_at TIMESTAMP DEFAULT NOW() ); -- 可以每天凌晨用定时任务Cron Job计算并插入前一天的指标第二步用Node.js定时任务填充这个表// cron/update-daily-metrics.ts import cron from node-cron; import prisma from prisma/client; const prisma new PrismaClient(); // 每天凌晨2点执行 cron.schedule(0 2 * * *, async () { const yesterday new Date(); yesterday.setDate(yesterday.getDate() - 1); const dateStr yesterday.toISOString().split(T)[0]; // 计算昨天的指标 const newRegistrations await prisma.user.count({ where: { createdAt: { gte: new Date(${dateStr}T00:00:00Z), lt: new Date(${dateStr}T23:59:59Z) } } }); const proSubscriptions await prisma.subscription.count({ where: { plan: PRO, status: ACTIVE, createdAt: { gte: new Date(${dateStr}T00:00:00Z), lt: new Date(${dateStr}T23:59:59Z) } } }); // ... 计算其他指标 // 插入或更新 await prisma.dailyBusinessMetrics.upsert({ where: { date: yesterday }, update: { newRegistrations, proSubscriptions }, create: { date: yesterday, newRegistrations, proSubscriptions } }); });第三步在Grafana里添加PostgreSQL作为数据源并创建仪表盘在Grafana里添加PostgreSQL数据源填数据库地址、用户名、密码。创建一个新的Dashboard添加一个Time series面板。在查询编辑器里写SQLSELECT date, new_registrations, pro_subscriptions FROM daily_business_metrics ORDER BY date;Grafana会自动把结果渲染成时间序列图。现在我可以在一个仪表盘里同时看到系统指标CPU、内存、请求率→ 来自Prometheus应用性能指标响应时间、错误率、慢查询→ 来自Sentry业务指标注册量、付费转化、留存率→ 来自PostgreSQL告警配置从邮件轰炸到精准通知监控系统搭好了但如果每次CPU超过10%就发一封告警邮件你会在3天内关掉所有告警。这就是告警疲劳Alert Fatigue。我的告警分级策略P0致命立即通知生产环境API完全不可用如负载均衡器返回502超过5分钟数据库连接完全断开支付系统故障通知方式电话 SMS SlackP1严重15分钟内通知API错误率超过5%持续10分钟服务器内存使用率超过90%核心业务指标如日注册量日环比下跌超过30%通知方式Slack 邮件P2需关注每日汇总非核心功能的错误服务器磁盘使用率超过80%业务指标周环比轻微波动通知方式每日汇总邮件在Prometheus Alertmanager里配置告警规则创建alerts.ymlgroups: - name: app_alerts rules: # P1告警API错误率超过5% - alert: HighApiErrorRate expr: rate(http_requests_total{status_code~5..}[5m]) / rate(http_requests_total[5m]) 0.05 for: 10m # 持续10分钟才触发避免短暂波动 labels: severity: P1 annotations: summary: API错误率超过5% description: 当前错误率{{ $value | humanizePercentage }} # P1告警内存使用率超过90% - alert: HighMemoryUsage expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) 0.9 for: 10m labels: severity: P1 annotations: summary: 服务器内存使用率超过90%然后在prometheus.yml里配置Alertmanager的地址alerting: alertmanagers: - static_configs: - targets: [localhost:9093] # Alertmanager的地址在Alertmanager里配置通知路由如P1告警发到SlackP0告警发到PagerDuty。结论性能监控与告警系统不是有了就好而是准确率要高疲劳度要低。独立开发者不需要像大厂那样搭建复杂的可观测性平台用几百个Dashboard和几千条告警规则但至少需要L1基础监控用Prometheus Grafana、L2应用性能监控用Sentry、以及一两条最核心的业务指标告警如日注册量为0。这三项加起来能拦住95%的线上事故。

相关新闻

SpringBoot3整合ShardingSphere实现高性能分库分表

SpringBoot3整合ShardingSphere实现高性能分库分表

1. 项目概述:SpringBoot3与ShardingSphere的强强联合 单表数据量突破千万级时,查询性能会呈现断崖式下降。去年我负责的电商系统就遇到了这个典型问题——订单表数据量达到3000万条后,最简单的 SELECT * FROM orders WHERE user_id? 查询都…

2026/10/15 15:16:10 阅读更多 →
2026年中科AI能否精准实现风险预警?答案即将揭晓!

2026年中科AI能否精准实现风险预警?答案即将揭晓!

在当今竞争激烈的商业环境中,企业面临着各种各样的风险,如市场波动、政策变化、技术革新等。准确的风险预警能够帮助企业提前做好应对准备,降低损失。随着AI技术的飞速发展,越来越多的企业开始寄希望于AI来实现精准的风险预警。那…

2026/9/26 14:13:49 阅读更多 →
IO模型与并发服务器

IO模型与并发服务器

阻塞IO 用户层:char buf[1024];recv(fd, buf, sizeof(0), 0); //程序卡在这里等待数据内核:1.检查socket接收缓冲区是否有数据 2.若无数据: 将进程状态设为TASK_INTERRUPTIBLE(可中断睡眠) 进程从CPU运行队列移出,触发调度器切…

2026/9/28 14:48:05 阅读更多 →

最新新闻

DiffiT实战:用视觉Transformer替代U-Net的扩散模型训练与调优

DiffiT实战:用视觉Transformer替代U-Net的扩散模型训练与调优

简介:DiffiT是NVIDIA团队提出的一种将视觉变换器引入扩散模型的图像生成新架构,面向生成式AI研究者、计算机视觉方向学生及扩散模型开发者,用于解决传统去噪网络过度依赖卷积残差U-Net、注意力机制设计缺乏统一范式的问题。资源包内含1个PDF文…

2026/10/15 15:16:00 阅读更多 →
我是怎么让文章被AI频繁引用的:一套GEO实操流程

我是怎么让文章被AI频繁引用的:一套GEO实操流程

越来越多人不再打开搜索引擎,而是直接问AI。过去我们比排名,现在比的是有没有被AI引用。我用半年时间跑通了一套GEO实操流程,七个步骤压在一张表里,照着做就能上手。一、GEO实操流程把流程拆开是七步,压成一张表&#…

2026/10/15 15:16:00 阅读更多 →
Linux + Qt/QML:解决 QtQuick.VirtualKeyboard.Plugins 模块加载失败与环境变量配置

Linux + Qt/QML:解决 QtQuick.VirtualKeyboard.Plugins 模块加载失败与环境变量配置

一、配置环境变量1、方法1:于终端中配置环境变量在启动YourApp 之前,于当前终端中配置环境变量:export QTDIR~/Qt5.14.2/5.14.2/gcc_64 export PATH$QTDIR/bin:$PATH export LD_LIBRARY_PATH$QTDIR/lib:$LD_LIBRARY_PATH export QT_PLUGIN_PA…

2026/10/15 15:16:00 阅读更多 →
Epicor交易业务类型:ERP库存与成本流转的语义协议层

Epicor交易业务类型:ERP库存与成本流转的语义协议层

简介:本资源是一份面向Epicor ERP系统实施顾问、财务与供应链模块运维人员及二次开发工程师的实务参考文档,聚焦交易业务类型(Transaction Business Types)的完整定义与账务逻辑说明。文档系统梳理了Epicor中近30类核心交易类型&a…

2026/10/15 15:16:00 阅读更多 →
Piccolo 仓库 Dear ImGui 集成指南:example_sdl_opengl2 在 Windows / Linux / macOS 上的完整构建与原理剖析

Piccolo 仓库 Dear ImGui 集成指南:example_sdl_opengl2 在 Windows / Linux / macOS 上的完整构建与原理剖析

游戏开发图形学 【免费下载链接】Piccolo Piccolo (formerly Pilot) – mini game engine for games104 项目地址: https://gitcode.com/gh_mirrors/pi/Piccolo 点击查看 免费下载 本指南以 example_sdl_opengl2 的 README 为核心,系统讲解 Dear ImGui …

2026/10/15 15:16:00 阅读更多 →
一个人运营10个账号是什么体验?工具选对了真的不累

一个人运营10个账号是什么体验?工具选对了真的不累

朋友问我:一个人管10个账号,是不是天天熬夜?我认真算了算,真正忙的其实不是“写”,而是“发”和“复盘”。同一个动作重复十遍,才是把人拖垮的根源。今天不堆方法论,只讲真实体验,以…

2026/10/15 15:14:58 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →