1. 前言

这篇文章的主题是记录一次程序的性能优化,在优化的过程中遇到的问题,以及如何去解决的。

为大家提供一个优化的思路,首先要声明的一点是,我的方式不是唯一的,大家在性能优化之路上遇到的问题都绝对不止一个解决方案。

2. 如何优化

首先大家要明确的一点是,脱离需求谈优化都是耍流氓。所以,有谁跟你说在 xx 机器上实现了百万并发,基本上可以认为是不懂装懂了,单纯的并发数完全是无意义的。

其次,我们优化之前必须要有一个目标。需要优化到什么程度,没有明确目标的优化是不可控的。再然后,我们必须明确的找出性能瓶颈在哪里,而不能漫无目的的一通乱搞。

3. 需求描述

这个项目是我在上家公司负责一个单独的模块。本来是集成在主站代码中的,后来因为并发太大,为了防止出现问题后拖累主站服务,所有由我一个人负责拆分出来。

对这个模块的拆分要求是,压力测试 QPS 不能低于 3 万,数据库负责不能超过 50%,服务器负载不能超过 70%,单次请求时长不能超过 70ms,错误率不能超过 5%。

环境的配置如下:

  • 服务器:4 核 8G 内存,CentOS 7 系统,SSD 硬盘

  • 数据库:MySQL 5.7,最大连接数 800

  • 缓存:Redis,1G容量。以上环境都是购买自腾讯云的服务。

  • 压测工具:Locust,使用腾讯的弹性伸缩实现分布式的压测。

需求描述如下:

  1. 用户进入首页,从数据库中查询是否有合适的弹窗配置。
  2. 如果没有,则继续等待下一次请求、如果有合适的配置,则返回给前端。

这里开始则有多个条件分支:

  • 如果用户点击了弹窗,则记录用户点击,并且在配置的时间内不再返回配置;

  • 如果用户未点击,则24小时后继续返回本次配置;

  • 如果用户点击了,但是后续没有配置了,则接着等待下一次。

4. 重点分析

根据需求,我们知道了有几个重要的点:

  • 需要找出合适用户的弹窗配置,

  • 需要记录用户下一次返回配置的时间并记录到数据库中,

  • 需要记录用户对返回的配置执行了什么操作并记录到数据库中。

5. 调优

我们可以看到,上述三个重点都存在数据库的操作,不只有读库,还有写库操作。

从这里我们可以看到,如果不加缓存的话,所有的请求都压到数据库,势必会占满全部连接数,出现拒绝访问的错误。同时因为 SQL 执行过慢,导致请求无法及时返回。

所以,我们首先要做的就是将写库操作剥离开来。提升每一次请求响应速度,优化数据库连接。

整个系统的架构图如下:

将写库操作放到一个先进先出的消息队列中来做。为了减少复杂度,使用了 Redis 的 list 来做这个消息队列。

然后进行压测,结果如下:

  • QPS 在 6000 左右 502 错误大幅上升至 30%;

  • 服务器 CPU 在 60%-70% 之间来回跳动;

  • 数据库连接数被占满 TCP 连接数为 6000 左右。

很明显,问题还是出在数据库。

经过排查 SQL 语句,查询到原因就是:找出合适用户的配置操作时每次请求都要读取数据库所导致的连接数被用完。

因为我们的连接数只有 800,一旦请求过多势必会导致数据库瓶颈。好了,问题找到了,我们继续优化。

更新的架构如下:

我们将全部的配置都加载到缓存中,只有在缓存中没有配置的时候才会去读取数据库。

接下来我们再次压测,结果如下:

  • QPS 压到 2 万左右的时候就上不去了;

  • 服务器 CPU 在 60%-80% 之间跳动;

  • 数据库连接数为 300 个左右,每秒 TCP 连接数为 1.5 万左右。

这个问题是困扰我比较久的一个问题。因为我们可以看到,我们 2 万的 QPS,但是 TCP 连接数却并没有达到 2 万。

我猜测,TCP 连接数就是引发瓶颈的问题,但是因为什么原因所引发的暂时无法找出来。

这个时候猜测,既然是无法建立 TCP 连接,是否有可能是服务器限制了 socket 连接数。

验证猜测,我们看一下,在终端输入 ulimit -n 命令,显示的结果为 65535。看到这里,觉得 socket 连接数并不是限制我们的原因,为了验证猜测,将 socket 连接数调大为100001。

再次进行压测,结果如下:

  • QPS 压到 2.2 万左右的时候就上不去了;

  • 服务器 CPU 在 60%-80% 之间跳动;

  • 数据库连接数为 300 个左右,每秒 TCP 连接数为 1.7 万左右。

虽然有一点提升,但是并没有实质性的变化。

接下来的几天时间,我发现都无法找到优化的方案。那几天确实很难受,找不出来优化的方案,过了几天再次将问题梳理了一遍,发现虽然 socket 连接数足够,但是并没有全部被用上。猜测每次请求过后,TCP 连接并没有立即被释放,导致 socket 无法重用。

经过查找资料,找到了问题所在:

TCP 链接在经过四次握手结束连接后并不会立即释放,而是处于 timewait 状态。会等待一段时间,以防止客户端后续的数据未被接收。

好了,问题找到了,我们要接着优化。

首先想到的就是调整 TCP 链接结束后等待时间。但是 Linux并没有提供这一内核参数的调整,如果要改必须要自己重新编译内核。幸好还有另一个参数net.ipv4.tcp_max_tw_buckets, timewait 的数量。默认是 180000。我们调整为6000。然后打开 timewait 快速回收和开启重用。

完整的参数优化如下:

#timewait 的数量,默认是 180000。
net.ipv4.tcp_max_tw_buckets = 6000net.ipv4.ip_local_port_range = 1024 65000#启用 timewait 快速回收。
net.ipv4.tcp_tw_recycle = 1#开启重用。允许将 TIME-WAIT sockets 重新用于新的 TCP 连接。
net.ipv4.tcp_tw_reuse = 1

我们再次压测,结果显示:

  • QPS 5万,服务器 CPU 70%;

  • 数据库连接正常,TCP 连接正常;

  • 响应时间平均为 60ms,错误率为 0%。

6. 结语

到此为止,整个服务的开发、调优、和压测就结束了。回顾这一次调优,得到了很多经验。最重要的是,深刻理解了Web 开发不是一个独立的个体,而是网络、数据库、编程语言、操作系统等多门学科结合的工程实践。这就要求 Web 开发人员有牢固的基础知识,否则出现了问题还不知道怎么分析查找。

最后: 可以关注公众号:伤心的辣条 ! 进去有许多资料共享!资料都是面试时面试官必问的知识点,也包括了很多测试行业常见知识,其中包括了有基础知识、Linux必备、Shell、互联网程序原理、Mysql数据库、抓包工具专题、接口测试工具、测试进阶-Python编程、Web自动化测试、APP自动化测试、接口自动化测试、测试高级持续集成、测试架构开发测试框架、性能测试、安全测试等。

如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “评论” “收藏” 一键三连哦!


好文推荐

转行面试,跳槽面试,软件测试人员都必须知道的这几种面试技巧!

面试经:一线城市搬砖!又面软件测试岗,5000就知足了…

面试官:工作三年,还来面初级测试?恐怕你的软件测试工程师的头衔要加双引号…

什么样的人适合从事软件测试工作?

那个准点下班的人,比我先升职了…

测试岗反复跳槽,跳着跳着就跳没了…

性能测试:记一次生产环境性能测试优化实践相关推荐

  1. 记一次生产环境脚本入侵检测与报警案例(检测特定目录被改动,自动报警)

    需求 : 特定目录,改动之后,自动报警. 转载来源 : 记一次生产环境脚本入侵检测与报警案例(简易版入侵检测系统) : http://www.safebase.cn/article-259102-1. ...

  2. 查看webpack版本_webpack小结-生产环境构建优化

    刚刚对我们前端项目做了一顿分析优化操作,因为接手时每次构建要花两分钟左右的时间,实在忍受不了,只能动手了.通过这次优化,重新温习了下 webpack 的一些知识.接下来会关于 webpack 展开写几 ...

  3. oracle修改卡顿,记一次生产环境卡顿优化过程:大事务并发回滚

    概述 最近生产环境有这么个现象,平时的订单调度只需要2s内可以出结果,但是多个人调度就会卡住,超过15分钟都没有结果出来,有时还会失败然后导致数据不准确. 下面记录一下生产环境卡顿时排查的过程. 1. ...

  4. CentOS(5.8/6.4)linux生产环境若干优化实战

    CentOS系统安装之后并不能立即投入生产环境使用,往往需要先经过我们运维人员的优化才行.在此讲解几点关于Linux系统安装后的基础优化操作.注意:本次优化都是基于CentOS(5.8/6.4). 下 ...

  5. CentOS(5.8/6.4)linux生产环境若干优化实战------就爱运维

    特别说明:本文来自就爱运维.特和所有博友分享.更多优化,请关注www.92yunwei.com后续内容以及分享. CentOS系统安装之后并不能立即投入生产环境使用,往往需要先经过我们运维人员的优化才 ...

  6. linux ntp时间立即同步命令_记一次生产环境部署NTP服务及配置时间同步

    概述 linux服务器在提供服务时,要和其他机器进行请求的交互,实际生产环境中,可能因为时间不同步,导致了服务异常. 下面介绍下怎么部署NTP服务来解决这个问题. ps:强烈吐槽下头条这个新排版功能, ...

  7. JVM|记一次生产环境 CPU 占用飙高问题解决

    目录 1 问题发现与背景 2 运维报警 3 问题定位与解决 (1)第一步,jps 查看 java pid (2)第二步,显示线程列表 ps -mp 42 -o THREAD,tid,time (3)第 ...

  8. 记一次生产环境java服务mqtt连接线程数过多的处理过程

    项目介绍: 本项目是负责发放机设备发放商品的平台.发放机设备是厂商控制,发放机平台是我们公司负责开发和维护.发放机设备和平台是通过mtqq协议通信的. mqtt开发客户端使用的是org.eclipse ...

  9. webpack5 - 之 生产环境的优化(dist压缩包、copy静态资源、缓存、代码切片、多线程打包、抽离重复代码 与 最小化 entry chunk)

    目录 1:webpack5 - 之 生产环境 dist压缩包 package.json webpack.pro.js npm run build效果 2:webpack5 - 之 生产环境 copy静 ...

最新文章

  1. 计算机图形软件---图形功能
  2. TypeError: 'function' object is not subscriptable
  3. Kilani and the Game
  4. android方块密码输入框,Android仿微信/支付宝的方块密码输入框
  5. android 获取当前画布,Android硬件位图填坑之获取硬件画布
  6. 二叉树的遍历(堆栈)
  7. 作者:蒋凡(1979-),男,百度外卖研发中心技术委员会主席、主任架构师,中国计算机协会专业会员。...
  8. python 科学计算设计_用Python做科学计算 pdf版
  9. Java基础---Java---网络编程---TCP的传输、客户端和服务端的互访、建立一个文本转换器、编写一个聊天程序
  10. 用 maven 命令启动项目和直接用tomcat 启动项目的区别
  11. 小米34寸带鱼屏显示器的耗电计算
  12. 【无标题】三星Xpress M2020打印机刷免芯片
  13. 推荐5款小众实用神器软件,功能强大,值得你去收藏
  14. stm32——自定义HID设备
  15. python国际象棋规则_如何使用Python编写一个国际象棋AI程序
  16. 裴蜀定理的证明与推广应用
  17. 数学辅导微信小程序设计与实现的源码+文档
  18. Create Associations
  19. Random Thoughts #2 罗列几个国内的VR类应用
  20. 2022优秀作文范文

热门文章

  1. 传奇gm命令怎么用_传奇GM常用命令
  2. 基于asp网上书店购物商城计算机毕业设计网站作品
  3. 我用Python抓取了【S11全球总决赛】直播评论,EDG nb
  4. 所有C#程序员必须知道的13件事
  5. java 导出表 sql_java中把SQL数据库中的表导出到excel中.怎么实现
  6. mysql where子句 参数_MySql——使用where子句过滤数据
  7. C++内存耗尽怎么办?
  8. VS2010下配置OpenCV2.2
  9. Java归去来第3集:Eclipse中给动态模块升级
  10. linux自学笔记--DNS服务器