ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

服务卡顿的分层排查方法

服务卡顿的分层排查方法 服务卡顿的分层排查方法“系统卡了”只描述了用户感受不能直接对应某个资源。页面转圈可能是请求没有到达服务、应用在线程池里等待、下游响应变慢也可能是结果已经返回但客户端处理受阻。排查的第一步是把模糊现象还原成路由、时间窗口和请求状态。不要一开始重启所有 Pod、清空缓存或同时修改多个参数。先阻止影响继续扩大再保存当前证据。一次操作只改变一个主要条件否则系统恢复后也很难知道是哪一步有效。第一层界定范围和时间先回答几个问题从何时开始所有用户还是部分用户哪些接口或任务受影响错误增加还是单纯变慢最近有什么发布或配置变化。平均延迟会掩盖少量慢请求应同时看请求量、延迟分布、超时和取消。抽取一个慢请求的关联标识沿网关、应用和下游 Trace 查各 Span 时间。若没有完整 Trace就用访问日志中的到达、转发和响应时间拼出最短证据链。日志时间需要校准不能把不同机器上未对齐的时间戳直接相减。此时也要决定是否限流、停止发布或关闭非核心功能。止损动作写明对象和恢复条件不要把“扩容”当作默认答案。扩容可能缓解容量不足也可能加剧数据库连接、缓存穿透和冷启动。第二层确认请求停在哪一跳网关出现 502、503、504 时先按本系统实际定义查看上游连接和响应日志。状态码可能由网关、服务或自定义异常映射产生不能仅凭数字断言根因。对比网关收到请求、连接上游和得到响应的时间判断请求是否已经进入应用。连接建立慢时再检查 DNS、TLS、负载均衡和监听队列。Linux 上可以查看监听队列溢出计数是否在故障窗口持续增长ss -lnt netstat -s | grep -i listen累计计数曾经增长不代表当前仍在溢出应取两次样本看增量并与应用监听地址、backlog 和入口连接模式一起分析。直接调大somaxconn也未必解决问题应用接受连接的速度、代理配置和请求处理能力都可能是限制。连接已建立但响应慢则继续到应用层。检查进行中请求、业务队列、线程池或事件循环、连接池等待和拒绝。CPU 低可能是大量任务在等锁或下游CPU 高可能是有效计算也可能是自旋、序列化或 GC。任何单一利用率都需要和请求状态对应。第三层看队列是否能够收敛服务有多少个排队位置应在架构图中写清网关、HTTP 线程池、业务执行器、消息队列、数据库连接池和下游客户端都可能等待。分别观察进入、完成、拒绝和当前等待。入口速率长期高于完成速率时队列只会增加。无界队列不会报告“已满”却会把问题变成内存增长与长时间等待。此时应限制新任务或降级非核心请求而不是继续扩张队列。队列恢复后还要确认已经超时的旧任务不会继续执行外部写入。线程 Dump 或 Goroutine Profile 用于看等待位置不是简单数WAITING。线程池空闲线程处于等待很正常。应按相同栈分组找在故障窗口显著增加的锁、连接获取和阻塞 I/O再与对应池指标核对。第四层把下游和共享资源纳入范围数据库慢查询、连接池耗尽、Redis 大命令和 RPC 超时都会把等待传回应用。查看下游自身延迟和错误同时检查调用方超时是否短于上游总预算、重试是否放大流量。客户端报连接超时既可能是池满也可能是 DNS、网络或目标端拒绝。多个服务同时变慢时优先寻找共享依赖和共同变更。不要让每个服务各自重试同一个故障依赖。断路器和入口限流可以帮助收敛但恢复阈值与半开探测需要验证避免所有实例同时恢复后再次压垮下游。缓存问题要区分未命中、击穿、雪崩和一致性等待。命中率下降只是现象继续看哪些键、为何失效、回源是否受控。清空缓存通常会扩大回源压力除非已经确认缓存内容错误且有预热或限流方案。第五层检查运行时与操作系统在 Linux 上vmstat可以提供 CPU、运行队列、不可中断等待和上下文切换的概览vmstat 1 5r持续高于可用 CPU 通常提示运行压力b表示处于不可中断睡眠的任务可能与 I/O 有关。上下文切换高不自动等于死锁还需结合进程线程数和 Profile。容器内看到的指标也可能缺少节点全局背景应同时查看 Cgroup 配额与节点竞争。CPU throttling 要看故障窗口内的增量和节流时间再与延迟对应。提高 limit 之前确认服务确实受配额限制并评估节点是否有容量。盲目增加所有 Pod 的 limit只会把竞争转移到节点层。Java 服务的 GC 检查同样需要相关性。jstat可以观察 GC 计数与累计时间jstat -gcutil PID 1000 10累计 GC 时间增长本身是正常现象曾发生 Full GC 也不能证明当前卡顿由它造成。应结合暂停事件、堆占用、分配速率和请求长尾。如果需要 Heap Dump 或 JFR先评估采集开销和数据敏感性。Go 服务则使用 runtime metrics、执行 Trace 和 pprof 查看 CPU、阻塞、互斥与 Goroutine。Profile 只在有代表性负载时采集并限制端点权限。看到大量 Goroutine 后继续按创建位置和等待栈分组不以数量直接判断泄漏。修复动作必须对应已验证原因将同步写入改成异步队列可能缩短接口等待却引入丢失、重复、延迟可见性和积压问题。只有业务允许异步并且队列有容量、幂等和失败处理时才适用。无锁队列也会在满时等待或拒绝选用哪种等待策略取决于 CPU 与延迟预算。本地缓存可以减少共享依赖调用但会增加内存和一致性复杂度。容量、过期、失效和租户隔离都要明确。固定一秒 TTL 或某个大小不是通用优化应根据数据变化与实际命中分布验证。扩线程池、连接池和副本数也一样先确认当前池是瓶颈并计算扩大后对下游的总并发。若根因是慢查询或锁竞争更多并发往往只会让等待者增加。复测使用原来的慢请求修复后回放同一请求分布比较各层 Span、队列增量、错误和资源而不是只看页面不再转圈。再验证超时、取消和依赖失败确认新方案不会在故障时积累任务。复盘留下时间线、受影响路径、关键证据、排除过的假设、变更和回归结果。没有确认根因时可以记录“当前通过限流恢复原因仍在调查”不要为了让报告完整而硬写结论。分层排查的价值是把“卡顿”逐步变成可验证的问题请求有没有到达、在哪个队列等待、谁持有资源、为何无法完成。只要每一步都由证据决定下一步故障处理就不会在重启、扩容和清缓存之间来回碰运气。
返回列表