
凌晨两点告警响起,这不是电话,而是整个技术团队被拉起的紧急呼叫。
XX省第一人民医院的门诊系统在晚高峰时段出现了严重卡顿,部分科室甚至无法登录。值班工程师小李第一时间检查了监控系统——所有指标正常:服务器CPU使用率40%(远低于警戒线),内存充足,网络流量平稳,数据库响应时间在可接受范围。
但患者的投诉电话持续不断:”系统卡死了!””挂号要五分钟!””收费窗口动不了了!”
小李感到困惑:监控显示一切正常,为什么用户体验如此糟糕?
1. 传统监控指标的致命盲区
李主任凌晨三点赶到数据中心。他首先查看了监控仪表板:CPU平均负载2.5(8核),内存使用率55%,网络带宽利用率30%,数据库连接池使用率60%——所有指标都在安全范围内。
但业务层的监控显示:挂号API平均响应时间从200毫秒上升到8秒,错误率从0.1%上升到15%。
“这怎么可能?”小李说,”应用服务器CPU才40%,数据库查询时间也正常,为什么响应会这么慢?”
李主任问:”你监控的是哪个层面的响应时间?”
“是应用服务器到网关的响应时间。”
“那数据库呢?前端呢?网络链路呢?”
小李摇了摇头——他们只监控了应用服务器的响应时间,没有监控端到端的完整链路。
这是一个典型的监控盲区问题。传统的监控体系过于关注基础设施层(服务器、网络、数据库),而忽略了业务链路层的真实用户体验。
老林建议立即进行链路追踪。他们在关键业务路径上插入了一些探针,很快发现:从用户点击”挂号”到页面返回,大部分时间(约7秒)消耗在数据库查询上,而不是应用处理。
但数据库监控显示查询响应时间只有50毫秒。矛盾在哪?
进一步深挖,他们发现了一个细节:数据库的”平均查询时间”是50毫秒,但这个平均值掩盖了长尾问题——90%的查询确实很快(10-20毫秒),但10%的查询因为锁等待或缓存失效,需要2-3秒甚至更长。平均值被大量的快速查询拉低了,但那些慢查询正好发生在门诊高峰期,直接影响用户体验。
这就是为什么”所有指标正常”但用户感觉”卡”——因为平均值掩盖了长尾延迟。
2. 缓存失效风暴:看不见的雪崩
小吴通过慢查询日志,锁定了几个最慢的查询。它们都涉及同一个表:DOCTOR_SCHEDULE(医生排班表)。这个表每天凌晨会被批量更新一次,之后正常增删改。
但为什么这个表的查询会突然变慢?
他们查看了数据库的缓存状态:InnoDBbufferpoolpagesdirty(脏页数)高达80%,而InnoDBbufferpoolpagesfree(空闲页)只有5%。这意味着缓冲池几乎被占满,新数据无法加载,必须进行大量磁盘I/O。
“是谁占用了这么多缓冲池?”李主任问。
他们启用了performanceschema,查看当前正在执行的热点查询。发现有一个后台任务:DailyReportJob,在早上九点二十分开始执行,它需要扫描DOCTORSCHEDULE全表(300万行)来计算统计指标。这个任务没有设限流,也没有错峰执行,直接冲击生产数据库。
更糟糕的是,这个任务的执行时间长达25分钟。在这25分钟内,业务查询不得不等待I/O资源,导致响应时间飙升。
“这个报表任务为什么在门诊高峰期跑?”李主任质问。
外包团队的回复是:”我们试过在晚上跑,但晚上数据量太大,要跑两个小时。所以改到白天,利用系统空闲期。”
但他们误解了”空闲”——门诊高峰期恰恰是系统最忙的时候,根本不是空闲期。
3. 从单点故障到系统思维
这次故障的修复相对简单:停止报表任务,系统响应迅速恢复正常。但李主任知道,这只是治标。
他们做了几件事:
1. 给报表任务加上了资源限制:CPU配额、内存限制、I/O优先级
2. 将报表任务的执行时间改到凌晨四点到六点,避开业务高峰
3. 优化报表SQL,增加了索引,将执行时间从25分钟降到3分钟
4. 购买并部署了APM(应用性能监控)工具,可以对每个请求进行全链路追踪
但更深层的反思在复盘会上。
老林说:”我们以前的监控思路是’看服务器’,现在是’看业务’。服务器指标只是手段,业务指标才是目的。以后我们的监控仪表板,首先要展示的是:挂号成功率、平均等待时间、门诊吞吐量、患者满意度(通过反馈系统)。如果这些业务指标正常,服务器指标哪怕有点波动也问题不大;但如果业务指标异常,服务器指标再’漂亮’也没用。”
小李问:”那为什么以前没意识到这点?”
李主任回答:”因为我们被’技术指标’绑架了。我们觉得CPU<80%、内存<85%就是健康。但实际上,用户体验是另一回事。一个慢查询可能CPU占用很低,但会让用户等得抓狂。"
“所以我们需要建立业务感知监控——不只是监控系统’活着没’,更要监控系统’好不好用’。”
4. 构建业务感知监控体系
接下来的三个月,团队构建了一套新的监控体系:
第一层:用户体验监控
– 部署前端真实用户监控(RUM),自动采集页面加载时间、API响应时间、错误率
– 关键业务路径设置SLA告警:挂号API P95响应时间>3秒告警,错误率>1%告警
第二层:应用链路追踪
– 使用OpenTelemetry标准,在每个微服务中植入探针
– 可以trace一个挂号请求的全链路:网关→挂号服务→医生排班服务→数据库→返回
– 快速定位瓶颈在哪个环节
第三层:资源质量监控
– 不只监控”连接池使用率”,还监控”活跃连接率”、”空闲连接率”、”等待获取连接的线程数”
– 不只监控”CPU使用率”,还监控”运行队列长度”、”上下文切换频率”
– 引入”资源争用指数”:多个业务竞争同一资源时,指数的变化趋势
第四层:业务指标监控
– 每小时门诊挂号量、退号率、平均候诊时间
– 每病区住院病人数、出院结算平均时长
– 药房发药量、处方审核通过率
– 这些业务指标与系统指标关联分析,发现隐性关联
5. 从”救火”到”防火”
新监控体系上线后,团队发现了多个之前忽略的隐患:
隐患一: 每天上午10:30-11:00,挂号响应时间会周期性上升。原来是某个后台任务StatisticsCollector在整点运行,它需要聚合前一天的统计数据。虽然它只跑5分钟,但在这5分钟内会锁住一些核心表。
解决方法:将统计任务拆分,部分移到夜间,部分改为增量计算,减少单次执行时间。
隐患二: 每月1号的住院结算特别慢。原因是财务科会在1号凌晨批量处理上月住院结算,这个任务会访问大量历史数据。虽然它在凌晨2点运行,但因为数据量太大,仍然会对白天产生余波(缓冲池污染)。
解决方法:将历史数据移到只读副本,结算任务走副本查询,不冲击生产库。
隐患三: 药房发药系统在午高峰(12:00-13:00)经常出现”短暂卡顿”。原因是药房医生会在这个时段集中提交处方,而处方审核服务需要调用外部医保接口进行合规性检查。医保接口响应慢(平均1.5秒)时,大量线程会阻塞等待。
解决方法:引入异步审核和本地缓存,将医保接口响应时间从关键路径中剥离。
6. 运维思维的转变
李主任在年度总结会上,分享了他对”现代运维”的理解:
“运维不再是’保证服务器不宕机’,而是’保证业务连续性’。服务器宕机只是最极端的情况,更多时候的问题是’业务慢’、’业务错’、’业务不稳定’。这些问题的根源可能不在服务器,而在于应用设计、数据模型、资源争用、外部依赖。”
“所以运维人员不能只懂服务器,要懂业务;不能只看指标,要看指标背后的用户感受。”
软佳的总监听后说:”你们现在的监控体系,已经接近我们给顶级三甲医院做的方案了。但我要补充一点:监控的终极目标不是发现更多问题,而是减少问题发生的频率和影响。也就是说,监控要能预警,预警之后能自动处置,自动处置不了才人工介入。”
“我们正在推一个’智能运维’平台,它能基于历史数据预测容量瓶颈,提前触发扩容;能识别异常模式,自动创建工单;甚至在检测到某些已知故障模式时,自动执行修复脚本。”
李主任问:”那运维人员岂不是要失业了?”
总监笑:”恰恰相反,运维人员要从’重复救火’中解放出来,去做更有价值的事——容量规划、架构优化、业务连续性设计。机器适合处理明确的规则,人适合处理模糊的决策。”
半年后,XX医院的HIS系统实现了连续200天无P1故障。李主任在科室内部的墙上写了两句话:
第一句: “指标正常 ≠ 系统健康”
第二句: “业务感知,才是运维的最终标尺”
互动话题
你们医院的监控体系能发现”业务异常”吗?还是只能看服务器指标?你有什么从”监控正常”到”业务异常”的排查经历?欢迎分享你们的监控实践。
> 基于真实医院场景改编,人物均为化名
立即免费试用门诊系统:https://app.kmhis.com/
International Version:https://app.kmhis.com/multi/
了解软佳门诊管理系统详情:https://www.kmhis.com/outpatient-management-system.html
支持8种语言:简体中文、繁体中文、香港中文、English、藏文、泰文、老挝语、越南语
说真的。这类问题我见过太多了。每次看到医院同事为选型头疼。我就想,要是早点有人把这些经验分享出来就好了。毕竟。选择不对。后面全是麻烦。选择对了。省心省力。还能提升整个机构的运行效率。希望这篇能帮到正在纠结的你。
你如果有具体需求。也可以去 www.kmhis.com 看看。那里有更详细的技术方案和案例。
