共计 2670 个字符,预计需要花费 7 分钟才能阅读完成。
案例背景
英雄互娱是国内出名游戏研发商和发行商,常常遇到热门线上游戏,在某霎时呈现大量登录申请,须要长期扩容资源的场景。为了让服务更好的应答突增并发申请压力,客户尝试通过把应用服务容器化部署,能通过 HPA(Horizontal Pod Autoscaling)的性能,疾速弹性主动扩容利用正本数来进步承载能力。
以下数据均从某已发行游戏的实在环境所得,其应用服务次要基于 Java 技术栈开发。
问题形容
该游戏利用部署在某私有云厂商的托管 K8S 环境中,通过一次更新后,将减少新服节点。以过往教训看,同时跑 6 个雷同利用的 Pod,服务的承载能力能够稳固达到每秒 5 万次的 RPS(Request per Second)。但在上线前压力测试后发现,同时跑 6 个 Pod 的 RPS 的承载峰值仅为 2 万出头。减少到 12 个 Pod 时(雷同资源配置),RPS 的承载峰值为 2.4 万左右,增长并不显著。进一步减少到 18 个 Pod(雷同资源配置),RPS 不再晋升,仍停留在 2.4 万左右。这就呈现问题了,该服务的承载能力无奈随着资源扩容线性增长,将会在高峰期极大影响游戏用户体验。显然瓶颈点会在服务自身,须要配合利用性能监测剖析伎俩来进一步追踪,找出瓶颈点并执行优化。
绿线为 RPS,峰值为 2.4 万
黄线为响应工夫(Response Time),峰值约为 1000ms
应用观测云定位问题的过程
观测云是零碎全链路数据可观测平台,非常适合高效定位上述问题根因。观测云利用性能监测反对应用 OpenTracing 协定的采集器,实现对分布式架构的利用进行端到端的链路剖析,并能与基础设施、日志、用户拜访监测进行关联剖析,疾速感知故障表象和定位故障根因,进步用户体验。
通过链路观测疾速定位问题方向
- 在容器服务环境中部署观测云的数据采集器 – DataKit,接入利用链路和日志数据。
- 服务在 21:00 到 22:00 点间进行压测,压测开始后,观测云利用性能监测的服务概览页面立刻显示出零碎实时运行状态,通过对 Pxx 的响应工夫做排序,疾速找到了响应工夫较长的服务。如下图所示:
- 点击该服务做进一步下钻,能够看到更具体的调用相干信息。如下图所示,发现「POST /xxx/v1/login/checklgn.lg」的响应工夫较长,并且随着压力的增大,均匀响应工夫会逐步减少。定位到该条服务链路须要做进一步的排查。
- 点击该服务调用,进一步下钻去探查资源详情,咱们留神到该服务执行会十分频繁的去调用 Redis(56 次),如下图所示。如果并发量增大,频繁调用该服务的时候,很可能会造成 Redis 上的微小压力。
- 从火焰图中,咱们能够看到有些 Redis 调用之间存在可疑的提早(留神红圈局部)。尽管,Redis 自身执行的工夫十分快,但因为调用间的提早拖慢了整体性能。
随着对系统的压力增大,该景象会更加显著。下图是压测高峰期产生的火焰图。从图中能够看到,两个 Redis 间的调用提早超过 2s。
所以,初步判断瓶颈点在 Redis 上,起因很可能是 Redis 端的压力较大,无奈即时响应前端调用所需的相干资源(例如:获取连贯),呈现了期待,从而导致在压测中整体的 RPS 上不去。此时,压测才刚开始不到 5 分钟,观测云疾速定位性能瓶颈点的能力让现场工程师着实震惊。
- 接下来就要进一步剖析是 Redis 配置的问题,还是拜访代码的问题了。首先开启 Redis 监测仪表板,从 Redis 的指标监控来看,在压测高峰期,呈现 CPU 被打满的状况。尝试对 Redis 相干的参数做了优化调整,比方,减少连接池中连接数的数量,长链接代替短连贯等的配置后,6 个 Pod 配置下压测后果 RPS 峰值可晋升到 3 万左右,但再减少 Pod 数量后,RPS 峰值简直没有变动。根因范畴进一步放大了,极有可能是拜访代码的问题。但这时候现场工程师稍有犯难,此时曾经是深更半夜了,这时候不可能再拉开发进来一一模块查看代码,但明明就快揭开问题根因了,要拖到今天再持续又切实心有不甘。
这时候能够用观测云的 Profiling 能力了。
通过 Profiling 性能发现代码层问题
观测云 Profiling 性能反对查看利用程序运行过程中 CPU、内存和 I/O 的应用状况,通过火焰图实时展现每一个办法、类和线程的调用关系和执行效率,帮忙优化代码性能。
现场再持续以下操作配置:
- 在观测云中开启 Profiling 的采集性能。
- Profiling 默认会 1 分钟左右上传一次统计数据。咱们对压测开始时的数据和运行一段时间后的数据做比拟,次要关注在「Lock Wait Time」和「Socket I/O Read Time」的指标上。如下图所示:
1) 压测开始时的 Profiling 数据
2) 压测一段时间后的 Profiling 数据
压测中是逐渐减少 RPS 的量,从上图的比照中,能够分明的看到压测过程中「Lock Wait Time」和「Socket I/O Read Time」的值会变得十分大。这里就可能存在瓶颈点。须要进一步下钻去看更具体的信息。
- 从 Redis 监控指标发现有大量的 Read 操作。所以,进一步看「Socket I/O Read Time」相干的详细信息。如下图所示:
调用程序按列从上往下,方块越长代表耗时占比越大。如上图红色标记的 3 个方块根本是最耗时的调用。在右侧,也能够通过不同的维度(类,办法,包等)进行数据查看。抉择其中 ActionHandler 持续往下一级下取信息。
- 在 ActionHandler 的详细信息中,能看到客户的代码中通过不同的实现办法在频繁调用 Redis 来实现相干的操作。如下图所示:
其中,以 setCacheModel 和 addCount 办法占用的工夫最多。
- 用同样的办法,发现其余的类办法中例如 Invocation.invoke() 等都存在相似频繁调用 Redis 的状况。这种状况会导致一个服务调用会产生大量的服务调用。当并发量大的时候,Redis 会成为热点,压力较大。
此时已是第二天凌晨,但终于找到了问题根因,确实因为代码内对 Redis 过于频繁的冗余调用所导致,甚至能清晰的定位到有问题的办法名,只待给开发提 ISSUE 即可。
最终功效
代码优化后,成果远超预期!
第二天,开发同学在观测云面板上,回溯到昨晚压测过程的时间段,看到了过后利用状态仪表板和 Profiling 仪表板数据,疾速了解了问题上下文,当天就实现了相干代码局部的优化并提了测试发版。
在当晚 21 点开始的新一轮的压测中,仍应用 6 个 Pod,RPS 跑到了超过 8 万峰值,相比第一次压测的 2 万 RPS 后果,性能足足晋升到 4 倍,同时响应工夫仍能管制在 800ms 以下,后果远超预期。
作者|观测云高级产品技术专家 —— 涂程