我是怎么一步步用go找出压测性能瓶颈
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~
序言:
笔者要在线上服务器load日志并且重放来测一些机器性能指标。模拟机器资源比较少,相对的被模拟的线上机器日志量大,假设线上单机qps有1w,那么5台机器组成的集群5w个qps。模拟机器压测客户端需要比5w个qps更快,才有比较意义。
第一章:HTTP初体验
正所谓“人生苦短,我用python”,python自带了urllib2、urllib3以及第三方的request。支持的代理访问、添加请求头基本满足功能需求。笔者用urllib2+multiprocessing库顺利了码完代码运行之,查看qps只有2k多,这显然远远低于需求。在加大进程数到cpu核数的数倍之多,也发现python仅能达到3k多。事出必有因,于是笔者便通过监控界面和shell小工具来找机器各种茬。
第二章:“中世纪黑暗期”
中世纪是黑暗漫长的时期,你做了很多事情,但却输出很少,留下来的是尝试后的经验总结。从cpu、内存、硬盘、网络各方面数据看。cpu使用率90%多,内存用满、硬盘wa很低、网络千兆网卡满载。最首先的是把千兆网卡机器替换成万兆网卡机器。查看timewait的连接数达到1w3多。那就先优化下看起来是"瓶颈"的东西。配置tcp_timestamps=1, tcp_tw_reuse=1, tpc_tw_recycle=1。sysctl -p生效下最新的配置,timewait连接数没下去,并发数没上来。既然硬件该做的设置都完了,那为什么别人家的露娜那么秀,我家的就是一坨屎呢。
再回过头来考虑程序架构问题。反省自己,首先urllib2、request库是网络io阻塞的,其次网络是短连接的,再次这么多进程切换系统开销也很大。在广袤的互联网海洋中遨游了一番,得出的结论就是grequest库可能是个解决办法。gevent是个协程库,它使用greenlet库提供的基于libev实现的高性能异步网络框架。Perfect!看起来是那么的完美。于是又尝试重写了程序。可是性能还是没有上去。那到底是不是python语言自身的限制问题,导致cpu高居不下,并发量又上不去呢?这里留个疑问,到文章的最后再来回答这个问题。
第三章:豁朗开朗
不甘心并且不再纠结于python,用当下网红golang重写下。golang的协程库号称是性能优秀,语言层面支持并行的,易于书写的利器。写完跑一跑,并发量还是上不去。一直保持打死都不放弃的精神,笔者再次用go的第二性能利器自带的golang pprof分析下代码的瓶颈。pprof生成的报告还可以用uber第三方组件go-torch生成更直观的火焰图。如图1所示。从火焰图查看出runtime.gcBgMarkWorker(gc:垃圾回收器),并且runtime.mallocgc也占用大量cpu时间。接着进行内存占用分析,使用go tool pprof -alloc_space replay1 /tmp/mem.prof查看如图2 所示,敲入top10命令,发现pull_worker累加分配了600多G内存,占比93%,list pull_worker命令找到该函数的瓶颈点。这个r4变量的初始化放在一个for循环内,r4是用于临时读取响应body,这个r4每次请求都重复分配,导致内存居高不下,解决办法是把他放在for循环外。
终章:总结
好了,至此单机并发量最高可以到3w了,也差不多达到计划的目标了。用两台这种机器组成的肉鸡就可以满足5w qps的请求了。再来回答之前留下来的问题,python语言并发上不去只是因为,库不支持从外面提供读buffer读取响应body,导致内存暴增,这不是语言本身的问题。相信python并没有那么差。同时,也熟悉了一门新利器go语言。go的原生协程支持和性能分析利器还是非常直观非常好用的,力荐!!
图1:性能瓶颈前的cpu火焰图
图2:找到内存使用最多的函数
找到增长最多的代码
问答
相关阅读
此文已由作者授权腾讯云+社区发布,原文链接:https://cloud.tencent.com/developer/article/1160803?fromSource=waitui
欢迎大家前往腾讯云+社区或关注云加社区微信公众号(QcloudCommunity),第一时间获取更多海量技术实践干货哦~
海量技术实践经验,尽在云加社区!
我是怎么一步步用go找出压测性能瓶颈的更多相关文章
- 记录一下通过分析Tomcat内部jar包找出request.getReader()所用的字符编码在哪里设置和起效的完整分析流程
前言: 之前写Java服务端处理POST请求时遇到了请求体转换成字符流所用编码来源的疑惑,在doPost方法里通过request.getReader()获取的BufferedReader对象内部的 R ...
- 我是如何一步步裹挟老板从.net 转到 java 阵营的
我是如何一步步裹挟老板从.net 转到 java 阵营的 仅记录从 .net(C#) 转到 java 的一些心路历程 时间点跨度 2016 — 2017 一.前 xx 公司同事群的一次聊天 前公司同事 ...
- SQL注入—我是如何一步步攻破一家互联网公司的
最近在研究Web安全相关的知识,特别是SQL注入类的相关知识.接触了一些与SQL注入相关的工具.周末在家闲着无聊,想把平时学的东东结合起来攻击一下身边某个小伙伴去的公司,看看能不能得逞.不试不知道,一 ...
- Windbg找出死锁
使用Windbg找出死锁,解决生产环境中运行的软件不响应请求的问题 前言 本文介绍本人的一次使用Windbg分析dump文件找出死锁的过程,并重点介绍如何确定线程所等待的锁及判断是否出现了死锁. 对于 ...
- 使用Windbg找出死锁,解决生产环境中运行的软件不响应请求的问题
前言 本文介绍本人的一次使用Windbg分析dump文件找出死锁的过程,并重点介绍如何确定线程所等待的锁及判断是否出现了死锁. 对于如何安装及设置Windbg请参考:<使用Windbg和SoS扩 ...
- 我是如何一步步编码完成万仓网ERP系统的(四)登录的具体实现
https://www.cnblogs.com/smh188/p/11533668.html(我是如何一步步编码完成万仓网ERP系统的(一)系统架构) https://www.cnblogs.com/ ...
- 我是如何一步步编码完成万仓网ERP系统的(十二)库存 1.概述
https://www.cnblogs.com/smh188/p/11533668.html(我是如何一步步编码完成万仓网ERP系统的(一)系统架构) https://www.cnblogs.com/ ...
- 我是如何一步步编码完成万仓网ERP系统的(十三)库存 2.加权平均价
https://www.cnblogs.com/smh188/p/11533668.html(我是如何一步步编码完成万仓网ERP系统的(一)系统架构) https://www.cnblogs.com/ ...
- 我是如何一步步编码完成万仓网ERP系统的(十四)库存 3.库存日志
https://www.cnblogs.com/smh188/p/11533668.html(我是如何一步步编码完成万仓网ERP系统的(一)系统架构) https://www.cnblogs.com/ ...
随机推荐
- [LeetCode 题解]:Gas Station
前言 [LeetCode 题解]系列传送门: http://www.cnblogs.com/double-win/category/573499.html 1.题目描述 There are ...
- mvc - Authorize授权
from : http://www.cnblogs.com/asks/p/4372783.html http://www.cnblogs.com/myindex/p/5479428.html
- 为啥我的Andrid百度SDK不能正常运行?
首先,百度SDK运行时候需要加载API Key,这个API Key是通过百度账号在百度里面申请到的,但是很可能大家没有注意到百度这个API Key申请的过程,其中很重要的一个步骤没有做好,而导致不能正 ...
- dataframe 转为list
首先使用np.array()函数把DataFrame转化为np.ndarray(),再利用tolist()函数把np.ndarray()转为list.
- THUSC2017酱油记
啊..酱油记三连发.. 果然SHTSC用掉太多RP了.. 其实感觉没什么好写的..都被考懵逼了.. 但还是写一下吧.. DAY0 月考完提前一天到了..什么也没发生 DAY1 先考试再开幕式..好奇怪 ...
- CF223C【Partial Sums】(组合数学+乱搞)
题面 传送门 题解 orz zzk 考虑这东西的组合意义 (图片来自zzk) \(a_i\)这个元素对\(k\)阶前缀和的第\(j\)个元素\(s_{k,j}\)的贡献就等于从\((0,i)\)走到\ ...
- [Swift]堆栈Stack的两种版本:(1)用类包装Stack (2)用泛型包装Stack
堆栈是一个在计算机科学中经常使用的抽象数据类型.堆栈中的物体具有一个特性: 最后一个放入堆栈中的物体总是被最先拿出来, 这个特性通常称为后进先出(LIFO)队列. 堆栈中定义了一些操作. 两个最重要的 ...
- UIView之setNeedsDisplay与drawRect 和 setNeedsLayout与layoutSubViews
1.UIView的setNeedsDisplay和setNeedsLayout方法 首先两个方法都是异步执行的.而setNeedsDisplay会调用自动调用drawRect方法,这样可以拿到 UI ...
- 虚拟机安装CentOS,网络配置
CentOS6和CentOS7,基础配置差不多. 安装CentOs6,过程:略: 安装完成后,系统默认启用动态ip,每次重启主机IP可能就会变化,搭配Xftp和Xshell工具会很难受,因此设置静态I ...
- 【Template】Miller Rabin
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #i ...