4万字《腾讯云技术实践精选集 2021》发布,点击下载 了解详情
写点什么

论每行代码的重要性:增加了一行代码,让我们提高了 3000% 的性能

  • 2022 年 1 月 16 日
  • 本文字数:2426 字

    阅读完需:约 8 分钟

论每行代码的重要性:增加了一行代码,让我们提高了3000%的性能

本文最初发布于Itamar Lechowicer博客,经原作者授权由 InfoQ 中文站翻译并分享

概述

我们公司运维着 15 个 Web 应用,主要的工作就是按需交付基于数据驱动的 Web 应用程序,用于支撑实时决策的制定。


这些应用的预期是在高负载下依然保持高可用。其中的主 Web 应用是一个历史遗留的大型多服务系统。系统中的大部分服务都有超过 15 年的历史并且经过了好几代人的重构。试想一下,负责编写系统代码的人现在可能已经离职或已经调整到其他岗位了。


过去几年我们团队的主要目标是就是针对这些服务进行性能优化。本次我将和你分享在性能优化的过程中,我们的一些主要经验总结和当时决定这么做的原因。

认知改变时刻

在某次事件中,用户增加了对我们应用的使用率,导致我们应用的数据流量大幅增加。在此事件过程中,用户抱怨我们的应用性能实在太差,以至于无法在应用上完成全套的业务流程。为此,我们开始利用监控工具分析应用的性能瓶颈。通过应用监控工具,我们发现服务在获取 DB 连接上消耗了 90%的响应时间。


但是 DB 看上去一切正常,所以,我们开始分析应用的 DB 连接池。分析发现,所有的 pod 将连接池中全部可用的连接都使用了。因此我们猜测服务在关闭连接上可能有问题。于是,我们花了几个小时时间检查代码,尝试找到连接没有被释放的地方。最终,我们的一个 TeamLeader 发现,pod 的存活探针在做一次简单的 DB 心跳请求之后没有释放 DB 连接。随后,我们立即在 pod 存活探针的请求中增加了一行用于释放 DB 连接的代码。影响是可怕的。眨眼间,应用的性能就开始稳定下来并且用户也恢复了正常使用。


就在此次事件的前一天,我们才执行过一次负载测试,以确保应用程序能够承受预期的使用量增长,测试结果表明应用的性能是在正常范围内的。然而事实证明这个测试结论是错误的,错误的测试结论误导我们以为应用程序没有需要修复的问题。我们深刻认识到了错误,我们需要做得更好。以下是我们在此次事件中学习到的一些经验和总结。

总结一:不要使用平均等待时长作为衡量服务负载的指标——核查应用的“尾部”值

当用户抱怨应用响应慢的时候,我们发现平均等待时长指标并没有明显的变化。当我们回顾了这些指标数据的时候,注意到了一些有趣的事情:之前我们是将平均请求时间作为服务等待的主要指标,因此,这次我们将 90%请求等待时长的数据做了一个图表,看看这个图表能不能反馈些信息。果不其然,在用户抱怨应用慢的时候,我们观察到图表中等待时长急剧增加。平均等待时长指标之所以没有明显变化,是因为太多的快速请求将平均值拉下来了。所以我的建议是,不使用平均等待时长,而使用 50%,90%,95%,99%的平均等待时长作为服务响应的指标。核查那些远远超过正常值范围的“尾部”值是非常重要的。

总结二:在性能优化上投入时间、工具和人力

要保持应用的高性能,我们必须具备以下条件:

  1. 负载测试和负载场景——具备可用的负载测试和负载场景非常重要。

  2. 应用监控工具(APM)——诸如 Dyanatrace,AppDynamics 和 Epsagon 等工具。APM 在监控服务上可以帮我们节约大量的时间。因此在生产环境安装至少一个 APM 是非常有必要的。

  3. 有效的日志——有效的日志是生产服务中断调查和性能问题调查的基本条件。因此你必须确保应用的日志是清晰且有用的。

  4. 日志分析工具——你不能从很多文件中读取和搜索日志,尤其当你的服务是集群的时候,通过文件读取日志将变得更加困难。因此,花时间投产一个诸如 ELK,Grafana 或 Splunk 的日志收集器和分析工具是非常有必要的。

  5. 专业的人力支撑——对于上面提到的知识或者工具,如果你的团队没有相关的专业人才,那么你将什么也干不了。

因此,针对复杂的系统,我建议投入专门的人和时间来处理。(例如,SRE 团队就能很好的胜任此项工作)

总结三:老系统将会消亡(除非我们激活它们)

作为人类,我们都有创造新事物的冲动和欲望,并且对创造出来的产品有一种所有权感。在软件的世界里,在我们需要处理的矛盾中,有时候也会包含这样的矛盾。一方面,有一个老系统需要我们维护;而另一方面,有一个炫酷的新系统我们想要去开发。那么这个时候,我们就需要决定将时间投入到那块。当我们面对这样的矛盾时,我们必须记住,如果我们不继续在老系统上进行开发和添加新功能,那么对老系统的了解会随着时间的推移而消失。因此,当我们面对系统故障或客户新需求时,由于缺少对老系统的了解或者能力问题,将无法达成目标。换句话说,当我们失去对于老系统的了解之后,系统的 MTTR(平均修复时间)上升了。

因此,我的建议是,要时常克制想要创造一个新的、炫酷事物的冲动,将时间投入到对老维护系统的熟悉和提升解决问题的能力上。另外,保持对老系统熟悉度的最佳方式就是尝试在老系统中添加代码。

结论四:每一行代码都很重要

有时,当我们在编写代码的时候,我们可能会忘记这些代码最终运行将在生产环境中,并为一个真实用户的真实工作服务。上面提到的我们亲身经历的案例中,仅仅只是因为程序员忘记了释放 DB 连接(一行代码而已),就可以干扰一个用户的正常工作(那些工作受影响的用户估计很不愿意给我们付钱)。


我的建议是:

想象一下(虽然很难),在世界的另一端,某个用户的工作完全依赖你编写的代码,同时试想一下,你写的每一行代码都将影响其使用应用的体验。

在 CI 或者 CD 环节执行负载测试。如果你想确保代码高可用,那么就针对每个即将投产的 PR 或版本都进行负载测试。

当你发现性能问题的时候,请怀疑每一行代码——据我们的经验,代码中的每个字符都有可能是导致性能的瓶颈。

总结

此文章阐述了我们在系统性能优化上的全部经验教训和体会心得,我希望通过此文章能够帮助你意识到系统性能缺陷所存在的潜在风险。

我认为,应用的性能应该被视为最高优先处理事项。因为和终端用户不能使用系统相比,漂亮的 UI 和炫酷的产品都显得微不足道。

我写的这些结论都是我根据日常性能优化的经验总结而来,因此,在我看来,上面的所有结论都是每一次成功的性能优化的基石。所以,我也希望你能发现它们的用处。

 

原文链接:

How Every Code Line Matters | We Improved Performance By 3000%

 

2022 年 1 月 16 日 18:516297

评论 1 条评论

发布
用户头像
非常赞同作者的观点,随着迭代的持续,系统会越来越复杂,一个好用的监测工具是非常有必要的。是问题定位的关键,也是性能优化的关键。
2022 年 01 月 24 日 10:32
回复
没有更多了
发现更多内容

小解c# foreach原理

喵叔

7月日更

JIRA 链接 bitbucket 提示错误 Invalid OAuth credentials

HoneyMoose

区块链技术如何赋能食品安全链路追溯

CECBC

Rust从0到1-并发-可扩展性

rust 并发 sync Concurrency send

[架构实战营]模块二作业

xyu

#架构实战营

数字人民币的基础:共识与信任

CECBC

优化和调整Spark应用程序(七)

数据与智能

spark 缓存 持久化

数字化转型下的数字经济新发展

CECBC

在腾讯,我的试用期总结

程序员鱼皮

Java c++ Python 大前端 后端

想在Java八股文面试中脱颖而出?这《1000道互联网大厂Java工程师面试题》必不可少!

Java 编程 程序员

想跳槽却简历石沉大海?一起来围观月薪20k的软件测试工程师真实简历 (含金量高面试题)

程序员阿沐

面试 软件测试 自动化测试 经验分享 简历

Druid 0.15 版本启动错误

HoneyMoose

CTF中的一些常见骚操作(可以没有,但不能不会)

网络安全学海

网络安全 信息安全 CTF 渗透测试 漏洞分析

想在Java八股文面试中脱颖而出?这《1000道互联网大厂Java工程师面试题》必不可少!

白亦杨

Java 编程 程序员

Nginx配置location

刘旭东

nginx 反向代理

nacos的作为服务配置怎么玩?

卢卡多多

nacos 服务 7月日更

JIRA 如何连接到云平台的 bitbucket

HoneyMoose

Linux之du命令

入门小站

Linux

【设计模式】总览

Andy阿辉

编程 程序员 设计模式 23种设计模式

【设计模式】工厂模式

Andy阿辉

编程 程序员 设计模式 23种设计模式

【Kubernetes技术专题】系统架构介绍

浩宇天尚

k8s 7月日更

在线XML转HTML工具

入门小站

工具

统一语言 = 领域模型 ?

escray

学习 极客时间 7月日更 如何落地业务建模

【设计模式】抽象工厂

Andy阿辉

编程 程序员 设计模式 23种设计模式 编程思想

大数据训练营-0711课后作业

cc

【涨知识】你不知道的Python常用开发工具!猿来这么多!

小阿杰

Python 后端 开发工具

勇于尝试新鲜事物,利于项目来积累学习经验

DisonTangor

职业规划

免费分享Mysql从入门到精通的优秀图书

Java入门到架构

从脑瘫患者重获交流到免开颅微创,脑机接口更安全了吗?

脑极体

图像的读取,显示与存储操作

IT蜗壳-Tango

7月日更

架构训练营模块二作业

Lemon

论每行代码的重要性:增加了一行代码,让我们提高了3000%的性能-InfoQ