[转]10+倍性能提高全过程--优酷帐号绑定淘宝帐号的TPS从500到5400的优化历程

摘要: # 10+倍性能提高全过程--优酷帐号绑定淘宝帐号的TPS从500到5400的优化历程 ## 背景说明 > 2016年的双11在淘宝上买买买的时候,天猫和优酷土豆一块儿作了联合促销,在天猫双11当天购物满XXX元就赠送优酷会员,这个过程须要用户在优酷侧绑定淘宝帐号(登陆优酷、提供淘宝帐号,优酷调用淘宝API实现两个帐号绑定)和赠送会员并让会员权益生效(看收费影片、免广告等等) >html

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

背景说明

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

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

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


会员部分的架构改造

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

主要的压测过程

screenshot.png

上图是压测过程当中主要的阶段中问题和改进,主要的问题和优化过程以下:github

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

优化过程当中碰到的好比淘宝api调用次数限流等一些业务问题就不列出来了spring


Passport部分的压力

因为用户进来后先要登陆而且绑定帐号,实际压力先到Passport部分,在这个过程当中最开始单机TPS只能到500,通过N轮优化后基本能达到5400 TPS,下面主要是阐述这个优化过程docker

Passport 核心服务分两个:

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

为了更好地利用资源每台物理加上部署三个docker 容器,跑在不一样的端口上(808一、808二、8083),经过bridge网络来互相通信数据库

Passport机器大体结构

screenshot.png

说明:这里的500 TPS到5400 TPS是指登陆和将优酷帐号和淘宝帐号绑定的TPS,也是促销活动主要的瓶颈api

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


太多SocketConnect异常(如上图)

在userservice机器上经过netstat也能看到大量的SYN_SENT状态,以下图:
tomcat

由于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

通常来讲一台机器可用Local Port 3万多个,若是是短链接的话,一个链接释放后默认须要60秒回收,30000/60 =500 这是大概的理论TPS值

同时观察这个时候CPU的主要花在sy上,最理想确定是但愿CPU主要用在us上,截图以下:

sy占用了30-50%的CPU,这太不科学了,同时经过 netstat 分析链接状态,确实看到不少TIME_WAIT:

因而让PE修改了tcp相关参数:下降 tcp_max_tw_buckets和开启tcp_tw_reuse,这个时候TPS能从1000提高到3000

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

竟然性能又回到了500,太沮丧了,其实最开始帐号绑定慢,Passport这边就怀疑taobao api是否是在大压力下不稳定,程序员通常都是认为本身没问题,有问题的必定是对方 :) ,taobao api那边给出调用数据都是1ms之内就返回了(alimonitor监控图表)。

因而怀疑从优酷的机器到淘宝的机器中间链路上有瓶颈,可是须要设计方案来证实这个问题在链路上,要不各个环节都会认为本身没有问题的,当时Passport的开发也只能拿到Login和Userservice这两组机器的权限,中间的负载均衡、交换机都没有权限接触到。

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

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

  1. 压测的时候在userservice ping 淘宝的机器;
  2. 将一台userservice机器从负载均衡上拿下来(没有压力),ping 淘宝的机器;
  3. 从公网上非优酷的机器 ping 淘宝的机器;

这个时候奇怪的事情发现了,压力一上来**场景一、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 的性能问题

这个问题具体参考我以前发表的优化文章http://www.atatech.org/articles/65232 。 主要是经过火焰图发现spring mapping path消耗了过多CPU的性能问题,CPU热点都在methodMapping相关部分,因而修改代码去掉spring中的methodMapping解析后性能提高了40%,TPS能从3000提高到4200.

著名的fillInStackTrace致使的性能问题

代码中的第二个问题是咱们程序中不少异常(fillInStackTrace),实际业务上没有这么多错误,应该是一些不重要的异常,不会影响结果,可是异常频率很高,对这种咱们能够找到触发的地方,catch住,而后不要抛出去(也就是别触发fillInStackTrace),打印一行error日志就行,这块也能省出10%的CPU,对应到TPS也有几百的提高。

screenshot.png

部分触发fillInStackTrace的场景和具体代码行(点击看高清大图):
screenshot.png

对应的火焰图(点击看高清大图):
screenshot.png

screenshot.png

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

整个useragent调用堆栈和cpu占用状况,作了个汇总(useragent不启用TPS能从4700提高到5400)
screenshot.png

实际火焰图中比较分散:
screenshot.png

最终经过对代码的优化勉勉强强将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) 

整个过程获得了淘宝API、优酷会员、优酷Passport、网络、蚂蚁等众多同窗的帮助,原本是计划去上海跟Passport的同窗一块儿复盘而后再写这篇文章的,结果一直未能成行,请原谅我拖延到如今才把你们一块儿辛苦工做的结果整理出来,可能过程当中的数据会有一些记忆上的小错误。
相关文章
相关标签/搜索