plantegg-10+倍性能提升全过程–优酷账号绑定淘宝账号的TPS从500到5400的优化历程

原文地址:https://plantegg.github.io/2018/01/23/10+%E5%80%8D%E6%80%A7%E8%83%BD%E6%8F%90%E5%8D%87%E5%85%A8%E8%BF%87%E7%A8%8B/

背景说明

2016年的双11在淘宝上买买买的时候,天猫和优酷土豆一起做了联合促销,在天猫双11当天购物满XXX元就赠送优酷会员,这个过程需要用户在优酷侧绑定淘宝账号(登录优酷、提供淘宝账号,优酷调用淘宝API实现两个账号绑定)和赠送会员并让会员权益生效(看收费影片、免广告等等)

这里涉及到优酷的两个部门:Passport(在上海,负责登录、绑定账号,下文中的优化过程主要是Passport部分);会员(在北京,负责赠送会员,保证权益生效)

在双11活动之前,Passport的绑定账号功能一直在运行,只是没有碰到过大促销带来的挑战

整个过程分为两大块:

  • 整个系统级别,包括网络和依赖服务的性能等,多从整个系统视角分析问题;
  • 但服务器内部的优化过程,将CPU从si/sy围赶us,然后在us从代码级别一举全歼。

系统级别都是最容易被忽视但是成效最明显的,代码层面都是很细致的力气活。

整个过程都是在对业务和架构不是非常了解的情况下做出的。

会员部分的架构改造

  • 接入中间件DRDS,让优酷的数据库支持拆分,分解MySQL压力
  • 接入中间件vipserver来支持负载均衡
  • 接入集团DRC来保障数据的高可用
  • 对业务进行改造支持Amazon的全链路压测

主要的压测过程

在这里插入图片描述
上图是压测过程中主要的阶段中问题和改进,主要的问题和优化过程如下:

- docker bridge网络性能问题和网络中断si不均衡    (优化后:500->1000TPS)
- 短连接导致的local port不够                   (优化后:1000-3000TPS)
- 生产环境snat单核导致的网络延时增大             (优化后生产环境能达到测试环境的3000TPS)
- Spring MVC Path带来的过高的CPU消耗           (优化后:3000->4200TPS)
- 其他业务代码的优化(比如异常、agent等)          (优化后:4200->5400TPS)

优化过程中碰到的比如淘宝api调用次数限流等一些业务原因就不列出来了

概述

由于用户进来后先要登录并且绑定账号,实际压力先到Passport部分,在这个过程中最开始单机TPS只能到500,经过N轮优化后基本能达到5400 TPS,下面主要是阐述这个优化过程

Passport部分的压力

Passport 核心服务分两个:

  • Login 主要处理登录请求
  • userservice 处理登录后的业务逻辑,比如将优酷账号和淘宝账号绑定

为了更好地利用资源每台物理加上部署三个docker 容器,跑在不同的端口上(8081、8082、8083),通过bridge网络来互相通讯

Passport机器大致结构

在这里插入图片描述

userservice服务网络相关的各种问题

太多SocketConnect异常(如上图)
在userservice机器上通过netstat也能看到大量的SYN_SENT状态,如下图:
在这里插入图片描述

因为docker bridge通过nat来实现,尝试去掉docker,让tomcat直接跑在物理机上
这时SocketConnect异常不再出现
在这里插入图片描述

从新梳理一下网络流程

docker(bridge)—-短连接—>访问淘宝API(淘宝open api只能短连接访问),性能差,cpu都花在si上;

如果 docker(bridge)—-长连接到宿主机的某个代理上(比如haproxy)—–短连接—>访问淘宝API, 性能就能好一点。问题可能是短连接放大了Docker bridge网络的性能损耗

当时看到的cpu si非常高,截图如下:
在这里插入图片描述
去掉Docker后,性能有所提升,继续通过perf top看到内核态寻找可用的Local Port消耗了比较多的CPU,gif动态截图如下(可以点击看高清大图):
在这里插入图片描述

注意图中ipv6_rcv_saddr_equal和inet_csk_get_port 总共占了30%的CPU (系统态的CPU使用率高意味着共享资源有竞争或者I/O设备之间有大量的交互。)

一般来说一台机器默认配置的可用 Local Port 3万多个,如果是短连接的话,一个连接释放后默认需要60秒回收,30000/60 =500 这是大概的理论TPS值【这里只考虑连同一个server IP:port 的时候】

这500的tps算是一个老中医的经验。不过有些系统调整过Local Port取值范围,比如从1024到65534,那么这个tps上限就是1000附近。

同时观察这个时候CPU的主要花在sy上,最理想肯定是希望CPU主要用在us上,截图如下:
在这里插入图片描述
规则:性能优化要先把CPU从SI、SY上的消耗赶到US上去(通过架构、系统配置);然后提升 US CPU的效率(代码级别的优化)

sy占用了30-50%的CPU,这太不科学了,同时通过 netstat 分析连接状态,确实看到很多TIME_WAIT:
在这里插入图片描述
cpu要花在us上,这部分才是我们代码吃掉的

于是让PE修改了tcp相关参数:降低 tcp_max_tw_buckets和开启tcp_tw_reuse,这个时候TPS能从1000提升到3000

鼓掌,赶紧休息,迎接双11啊
在这里插入图片描述

测试环境优化到3000 TPS后上线继续压测

居然性能又回到了500,太沮丧了,其实最开始账号绑定慢,Passport这边就怀疑taobao api是不是在大压力下不稳定,一般都是认为自己没问题,有问题的一定是对方。我不觉得这有什么问题,要是知道自己有什么问题不早就优化掉了,但是这里缺乏证据支撑,也就是如果你觉得自己没有问题或者问题在对方,一定要拿出证据来(有证据那么大家可以就证据来讨论,而不是互相苍白地推诿)。

这个时候Passport更加理直气壮啊,好不容易在测试环境优化到3000,怎么一调taobao api就掉到500呢,这么点压力你们就扛不住啊。 但是taobao api那边给出调用数据都是1ms以内就返回了(alimonitor监控图表–拿证据说话)。

看到alimonitor给出的api响应时间图表后,我开始怀疑从优酷的机器到淘宝的机器中间链路上有瓶颈,但是需要设计方案来证明这个问题在链路上,要不各个环节都会认为自己没有问题的,问题就会卡死。但是当时Passport的开发也只能拿到Login和Userservice这两组机器的权限,中间的负载均衡、交换机都没有权限接触到。

在没有证据的情况下,肯定机房、PE配合你排查的欲望基本是没有的(被坑过很多回啊,你说我的问题,结果几天配合排查下来发现还是你程序的问题,凭什么我要每次都陪你玩?),所以我要给出证明问题出现在网络链路上,然后拿着这个证据跟网络的同学一起排查。

讲到这里我禁不住要插一句,在出现问题的时候,都认为自己没有问题这是正常反应,毕竟程序是看不见的,好多意料之外逻辑考虑不周全也是常见的,出现问题按照自己的逻辑自查的时候还是没有跳出之前的逻辑所以发现不了问题。但是好的程序员在问题的前面会尝试用各种手段去证明问题在哪里,而不是复读机一样我的逻辑是这样的,不可能出问题的。即使目的是证明问题在对方,只要能给出明确的证据都是负责任的,拿着证据才能理直气壮地说自己没有问题和干净地甩锅。

在尝试过tcpdump抓包、ping等各种手段分析后,设计了场景证明问题在中间链路上。

设计如下三个场景证明问题在中间链路上:

  1. 压测的时候在userservice ping 依赖服务的机器;
  2. 将一台userservice机器从负载均衡上拿下来(没有压力),ping 依赖服务的机器;
  3. 从公网上非我们机房的机器 ping 依赖服务的机器;

这个时候奇怪的事情发现了,压力一上来场景1、2的两台机器ping淘宝的rt都从30ms上升到100-150ms,场景1 的rt上升可以理解,但是场景2的rt上升不应该,同时场景3中ping淘宝在压力测试的情况下rt一直很稳定(说明压力下淘宝的机器没有问题),到此确认问题在优酷到淘宝机房的链路上有瓶颈,而且问题在优酷机房出口扛不住这么大的压力。于是从上海Passport的团队找到北京Passport的PE团队,确认在优酷调用taobao api的出口上使用了snat,PE到snat机器上看到snat只能使用单核,而且对应的核早就100%的CPU了,因为之前一直没有这么大的压力所以这个问题一直存在只是没有被发现。

于是PE去掉snat,再压的话 TPS稳定在3000左右

到这里结束了吗? 从3000到5400TPS

优化到3000TPS的整个过程没有修改业务代码,只是通过修改系统配置、结构非常有效地把TPS提升了6倍,对于优化来说这个过程是最轻松,性价比也是非常高的。实际到这个时候也临近双11封网了,最终通过计算(机器数量*单机TPS)完全可以抗住双11的压力,所以最终双11运行的版本就是这样的。 但是有工匠精神的工程师是不会轻易放过这么好的优化场景和环境的(基线、机器、代码、工具都具备配套好了)

优化完环境问题后,3000TPS能把CPU US跑上去,于是再对业务代码进行优化也是可行的了。

进一步挖掘代码中的优化空间

双11前的这段封网其实是比较无聊的,于是和Passport的开发同学们一起挖掘代码中的可以优化的部分。这个过程中使用到的主要工具是这三个:火焰图、perf、perf-map-java。相关链接:

  • http://www.brendangregg.com/perf.html
  • https://github.com/jrudolph/perf-map-agent

通过Perf发现的一个SpringMVC 的性能问题

这个问题具体参考我之前发表的优化文章。 主要是通过火焰图发现spring mapping path消耗了过多CPU的性能问题,CPU热点都在methodMapping相关部分,于是修改代码去掉spring中的methodMapping解析后性能提升了40%,TPS能从3000提升到4200.

著名的fillInStackTrace导致的性能问题

代码中的第二个问题是我们程序中很多异常(fillInStackTrace),实际业务上没有这么多错误,应该是一些不重要的异常,不会影响结果,但是异常频率很高,对这种我们可以找到触发的地方,catch住,然后不要抛出去(也就是别触发fillInStackTrace),打印一行error日志就行,这块也能省出10%的CPU,对应到TPS也有几百的提升。
在这里插入图片描述
部分触发fillInStackTrace的场景和具体代码行(点击看高清大图):
在这里插入图片描述
对应的火焰图(点击看高清大图):
在这里插入图片描述
在这里插入图片描述

解析useragent 代码部分的性能问题

整个useragent调用堆栈和cpu占用情况,做了个汇总(useragent不启用TPS能从4700提升到5400)
在这里插入图片描述
实际火焰图中比较分散:
在这里插入图片描述

最终通过对代码的优化勉勉强强将TPS从3000提升到了5400(太不容易了,改代码过程太辛苦,不如改配置来得快)

优化代码后压测tps可以跑到5400,截图:
在这里插入图片描述

最后再次总结整个压测过程的问题和优化历程

- docker bridge网络性能问题和网络中断si不均衡    (优化后:500->1000TPS)
- 短连接导致的local port不够                   (优化后:1000-3000TPS)
- 生产环境snat单核导致的网络延时增大             (优化后能达到测试环境的3000TPS)
- Spring MVC Path带来的过高的CPU消耗           (优化后:3000->4200TPS)
- 其他业务代码的优化(比如异常、agent等)         (优化后:4200->5400TPS)

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/573052.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源AI引擎|企业合同管理:自然语言处理与OCR技术深度融合

一、企业应用:合同智能管理 结合NLP和OCR技术,企业可以构建智能化的合同管理系统,实现合同的自动化审查、风险评估和知识抽取。这样的系统不仅能够提高合同处理的效率,还能够降低人为错误,加强风险控制。 例如&#x…

计算机视觉之三维重建(4)---三维重建基础与极几何

文章目录 一、三维重建基础1.1 问题引入1.2 线性解法1.3 非线性解法1.4 多视图几何的关键问题 二、极几何与基础矩阵2.1 极几何2.2 极几何特例2.3 本质矩阵2.4 本质矩阵的性质2.5 基础矩阵2.6 基础矩阵的性质 三、基础矩阵估计 一、三维重建基础 1.1 问题引入 1. 从单张图像恢…

[TS面试]keyof和typeof关键字作用?

keyof和typeof关键字作用? keyof 索引类型查询操作符, 获取索引类型属性名, 构成联合类型 typeof 获取一个变量或者对象的类型 let str:string ‘hello’ // typeof str >:string keyof typeof 获取 联合类型的key enum A{A, B, C }type unionType keyof typeof A; /…

【嵌入式——C语言】VScode编写C程序、交叉编译

【嵌入式——C语言】VScode编写C程序、交叉编译 第一步第二步第三步第四步第五步第六步第七步第八步 第一步 下载Visual Studio Code下载地址 然后直接安装就可以了。 第二步 前提是你的电脑上安装了WSL。。。 打开vscode的扩展,输入WSL进行安装 安装完之后在窗…

【SAP2000】在框架结构中应用分布式面板荷载Applying Distributed Panel Loads to Frame Structures

在框架结构中应用分布式面板荷载 Applying Distributed Panel Loads to Frame Structures 使用"Uniform to Frame"选项,可以简单地将荷载用于更多样化的情况。 With the “Uniform to Frame” option, loads can be easily used for a greater diversity of situat…

机器人寻路算法双向A*(Bidirectional A*)算法的实现C++、Python、Matlab语言

机器人寻路算法双向A*(Bidirectional A*)算法的实现C、Python、Matlab语言 最近好久没更新,在搞华为的软件挑战赛(软挑),好卷只能说。去年还能混进32强,今年就比较迷糊了,这东西对我…

【安全用电管理系统的应用如何保证用电安全】Acrel-6000安科瑞智慧安全用电解决方案

政策背景 国家部委 ※2017年5月3日国务院安委会召开电气火灾综合治理工作视频会议,决定在全国范围内组织开展为期3年的电气火灾综合治理工作。 公安部领导 ※公安部副部长李伟强调:向科技要战斗力,加快推进“智慧消防”建设不断提升火灾防控…

夜莺浏览日志、filebeat采集日志(四)

文章目录 一、elasticsearch二、filebeat三、日志分析 一、elasticsearch docker启动 docker run -d -p 9200:9200 -p 9300:9300 --restartalways -e ES_JAVA_OPTS"-Xms512m -Xmx512m" \ -e discovery.typesingle-node -e xpack.security.enabledtrue -e ELASTIC_P…

01 | 深入理解 Swoole 的底层加载原理

首发原文链接:深入理解 Swoole 的底层加载原理 PHP 扩展加载 我们从 php-src/sapi/cli/php_cli.c:1159 文件的入口函数 int main(int argc, char *argv[]) 开始分析。 大家可以先看下面这张图,描述了整个关键函数的加载、调用流程。从模块的初始化&…

C++初学者:像C#一样优雅写程序

C语言的强大,在于自由自在,你可以随便怎么写程序,不讲格式,可以很整齐,也可以鬼画符,只要能运行就可以了,程序员可以自由发挥。 如图: 国际C语言大赛中的代码 图2 C的语言更强大&…

Django auth模块

【一】命令行创建用户 【1】语法 python manage.py createsuper【2】示例 用户名 默认是是电脑名称 邮箱 可以填也可以不填 密码 terminal中:输入密码不显示出来manage.py中:明文输入输入密码太简单会提示 Username (leave blank to use administra…

【爬虫基础】第6讲 opener的使用

在爬虫中,opener是一个用来发送HTTP请求的对象。它可以用来模拟浏览器发送请求,包括设置请求头、处理Cookie等操作。使用opener可以实现一些高级功能,如模拟登录、处理验证码等。 方法1: from urllib.request import Request,bu…