澳门美高梅手机网站VR只玩黄油?前几日出售的《毁灭战士VFR》也能射爆

项目背景

我们本着nginx事件框架和openssl协议栈举行了有些深度改造,以升级nginx的HTTPS完全握手总括性能。
鉴于原生nginx使用当地CPU做RSA总括,ECDHE_RSA算法的单核处理能力只有400
qps左右。中期测试时的并发性能很低,固然开了24核,性能也不可能领先1万。
基本功效在2018年终就做到了支出,线下测试也并未察觉题目。经过优化后的习性提升几倍,为了测试最大性能,使用了诸多客户端并发测试https性能。很快就遇上了一部分问题:

  1. 首先个问题是nginx有极低概率(亿分之一)在不同地点 core
    dump。白天线下压力测试2W
    qps一般都要两两个时辰才出四遍core。每一次晌午睡觉在此以前都会将新型的调节代码编译好并启动测试,到清晨复苏第一眼就会去查看机器并祈祷不要出core,不幸的是,一般都会有几个到几十个core,并且会意识经常是在一个刻钟点集中core
    dump。线上灰度测试运行了6天,在第6天的早上才集中core
    dump了几十次。这样算来,这么些core dump的票房价值至少是亿分之一了。
    不过和面试题目中多线程不同的是,nginx采纳的是多进程+全异步事件驱动的编程形式(近期也帮忙了多线程,但只是针对IO的优化,要旨机制依旧多进程加异步)。在webserver的实现背景下,多进程异步相相比较多线程的亮点是性质高,没有太多线程间的切换,而且内存空间独立,省去线程间锁的竞争。当然也有欠缺,就是异步情势编程非常复杂,将部分逻辑上连接的轩然大波从半空和岁月切割,不切合人的常规思考习惯,出了问题后相比难追查。另外异步事件对网络和操作系统的底部知识要求较高,稍不小心就便于挖坑。
  2. 其次个问题是高并发时nginx存在内存泄漏。在流量低的时候从不问题,加大测试流量就汇合世内存泄漏。
  3. 其六个问题,因为大家对nginx和openssl的要紧代码都做了有的改建,希望提高它的属性。那么如何找到性能热点和瓶颈并不停优化呢?

中间第一和第二个问题的背景都是,只有现身上万qps以上时才有可能出现,几百要么一两千QPS时,程序没有其他问题。

为了让玩家感受到更强的爽快感,当准备传送或是接触到《毁灭战士》中遍布地图的跳板时,游戏会跻身子弹时间状态,此时用武器可以射击冤家头部更易瞄准,也能看到更刺激的爆头场地。

perf,oprofile,gprof,systemtap

linux世界有好多特别好用的特性分析工具,我采取几款最常用的简易介绍下:

  1. [perf](Perf
    Wiki
    )应该是最全面最有利于的一个特性检测工具。由linux内核指导并且一路立异,基本能满意普通使用。**引进我们使用**。
    2.
    oprofile,我觉着是一个较老式的性能检测工具了,基本被perf取代,命令使用起来也不太有利。比如opcontrol
    –no-vmlinux , opcontrol –init等一声令下启动,然后是opcontrol –start,
    opcontrol –dump, opcontrol
    -h截至,opreport查看结果等,一大串命令和参数。有时候使用还易于忘记开始化,数据就是空的。
    3.
    gprof一言九鼎是指向应用层程序的性能分析工具,缺点是需要重新编译程序,而且对程序性能有局部影响。不援助基础层面的有些总结,优点就是应用层的函数性能总括相比较娇小,接近我们对常见性能的知晓,比如各样函数时间的运转时刻,,函数的调用次数等,很人性易读。
    4.
    systemtap
    其实是一个运行时先后如故系统消息收集框架,首要用来动态追踪,当然也能用做性能分析,功用最强大,同时利用也针锋相对复杂。不是一个简单的工具,可以说是一门动态追踪语言。比方程序出现特别麻烦的性能问题时,推荐应用
    systemtap。

此地再多介绍一下perf命令,tlinux系统上默认都有安装,比如通过perf
top就能列举出当下系统或者经过的热门事件,函数的排序。
澳门美高梅手机网站,perf
record能够纪录和保留连串或者经过的性能事件,用于末端的分析,比如接下去要介绍的火焰图。

《毁灭战士VFR》购买地方>>

bug怎样重现?

此时的调试效率已经很低了,几万QPS连续压力测试,多少个钟头才出一遍CORE,然后修改代码,添加调试日志。几天过去了,毫无进展。所以必须要在线下结构出稳定的core
dump环境,这样才能加速debug效能。
尽管还尚未察觉根本原因,可是发现了一个很可疑的地点:
出CORE比较集中,通常是在凌晨4,5点,清晨7,8点的时候
dump几十个CORE。

《毁灭战士VFR》前天一度正式发售,Steam国区及零售商杉果定价均为99元,杉果购买还可应用优惠券省下5元。需要专注的是游玩近日仅辅助HUAWEIVive和PSVR,Oculus玩家暂时无缘本作了。

火焰图 flame graph

perf有一个瑕疵就是不直观。火焰图纵使为了然决这一个题材。它可以以矢量图形化的不二法门显示事件热点及函数调用关系。
比如我经过如下几条命令就能绘制出原生nginx在ecdhe_rsa cipher
suite下的性能热点:

  1. perf record -F 99 -p PID -g — sleep 10
  2. perf script | ./stackcollapse-perf.pl > out.perf-folded
  3. ./flamegraph.pl out.perf-folded>ou.svg

澳门美高梅手机网站 1直接通过火焰图就能观察各样函数占用的比例,比如上图就能明了地精通rsaz_1024_mul_avx2和rsaz_1024_sqr_avx2函数据为己有了75%的采样比例。这咱们要优化的对象也就特别了然了,能不可能防止这六个函数的测算?或者选择非本地CPU方案实现它们的总结?
自然是足以的,我们的异步代理总括方案正是为精晓决这么些题目,

澳门美高梅手机网站 2
从上图可以见见,热点事件里早已没有RSA相关的计算了。至于是什么做到的,前面有时间再写专门的小说来分享。

2016版《毁灭战士》中标志性的技能壮烈击杀也取得保留,当玩家通过发射消耗敌人生命,使敌人进入踉跄状态时,只要瞄准敌人传送即可自动发动壮烈击杀,把仇人身体打成碎块,并为自身回复生命。

心态

为了缓解地点提到的core
dump和内存泄漏问题,花了大概三周左右光阴。压力很大,精神中度紧张,
说实话有些为难,看似多少个很简单的题材,搞了这般长日子。心里自然不是很爽,会略微心急,特别是种类的要紧上线期。但哪怕这样,整个过程自己要么不行自信并且斗志昂扬。我间接在告知自己:

  1. 调试BUG是一回不行难能可贵的学习机会,不要把它当作是承受。不管是线上如故线下,可以主动地,高效地追查BUG特别是有难度的BUG,对友好来说五回相当可贵的读书机会。面对诸如此类好的上学机会,自然要充满热情,要如饥似渴,回首一看,假设不是因为这多少个BUG,我也不会对有些工具有更深刻地打听和应用,也就不会有这篇文档的发出。
  2. 不论是什么样的BUG,随着时光的延迟,肯定是可以解决的。这样考虑,其实会轻松很多,特别是接替新品类,改造复杂工程时,由于对代码,对作业一伊始并不是很了然,需要一个过渡期。但关键是,你要把那么些问题放在心上。白天上班有无数工作搅扰,上下班途中,早上睡觉前,大脑反而会愈发清醒,思路也会更加分明。特别是光天化日上班时容易思维一直,陷入一个长日子的误区,在那边调试了半天,结果大脑一片混沌。睡觉前或者上下班途中一个人时,反而能想出一些新的笔触和章程。
  3. 绽放地研商。遭遇问题并非不好意思,不管多简单,多低级,只要这么些题目不是您google一下就能拿到的结论,大胆地,认真地和组内同事谈论。这一次BUG调试,有三回重大的座谈给了自身很大的启发,特别是最终reusable的题材,也是组内同事的啄磨才点燃了我的灵感。谢谢我们的匡助。

《毁灭战士VFR》由2016年发售的《毁灭战士》原班人马打造,出自射击游戏鼻祖id
Software之手,质料应该说是非凡典型。游戏在镜头上基本再次出现了《毁灭战士》的效能,但这并不是照搬原版的移植骗钱作,而是所有全新剧情故事的新作。

弱网络环境的社团 traffic control

联想到夜间有众多的网络硬件调整及故障,我推断这一个core
dump可能跟网络质料相关。**特意是网络刹那时不安静,很容易触发BUG导致大量的CORE
DUMP。**
最先河我考虑过使用TC(traffic
control)工具来布局弱网络环境,但是转念一想,弱网络环境导致的结果是什么?分明是网络请求的各个异常啊,所以还不如直接协会各个相当伸手来复现问题。于是准备构造测试工具和环境,需要满意多少个标准化:

  1. 并发性能强,可以同时发送数万居然数十万级以上qps。
  2. 伸手需要自然几率的可怜。特别是TCP握手及SSL握手阶段,需要特别中止。

traffic
control是一个很好的布局弱网络环境的工具
,我事先用过测试SPDY协议性能。可以决定网络速率、丢包率、延时等网络环境,作为iproute工具集中的一个工具,由linux系统自带。但正如劳累的是TC的配备规则很复杂,facebook在tc的底子上包裹成了一个开源工具apc,有趣味的可以试试。

关于《毁灭战士VFR》,玩家们肯定还有一个最大的疑惑,这就是“VFR”中的“F”是何等看头呢?Bethesda市场主任彼得(Peter)Hines曾在推特上交给过答复,“这里的F和BFG中的F是一个趣味。”而前BioWare员工麦克(Mike)Laidlaw热心地为不太通晓BFG的玩家做出了说明,“是‘friendly’的情趣。”

特性热点分析

到此,经过改建的nginx程序尚未core
dump和内存泄漏方面的高风险了。但那显然不是我们最关切的结果(因为代码本该如此),大家最关注的题材是:

  1. 代码优化前,程序的瓶颈在什么地方?可以优化到如何程度?
  2. 代码优化后,优化是否干净?会产出什么新的习性热点和瓶颈?
    本条时候大家就需要部分工具来检测程序的性质热点。

具体来说呢,就是玩家不再化身无所无法的非凡“毁灭战士”(Doom
盖伊),而是扮演一名在恶魔入侵时遇害的地理学家,他的发现留存在机械中,并通过取得了决定其他机器人的力量。

WRK压力测试工具

由于高并发流量时才可能出core,所以率先就需要找一个属性强大的压测工具。
WRK是一款特别可观的开源HTTP压力测试工具,选拔多线程
+
异步事件驱动的框架,其中事件机制使用了redis的ae事件框架,协议分析采纳了nginx的相关代码。
相比之下ab(apache
bench)等观念压力测试工具的亮点就是性质好,基本上单台机器发送几百万pqs,打满网卡都没有问题。
wrk的弱项就是只协助HTTP类协议,不辅助其他协商类测试,比如protobuf,此外数码体现也不是很有益。

nginx的测试用法: wrk -t500 -c2000 -d30s class=”invisible”>https:// class=”visible”>127.0.0.1:8443/index.ht class=”invisible”>ml

除此之外剧情之外,《毁灭战士VFR》的操作办法也做了适应VR的转移。玩家可以用左手的控制器为温馨选定移动地方,按下控制器后游戏主角就会连忙冲到指定地方,而右边的控制器则用来瞄准射击,体验真正的射击感觉。当然,玩家也得以小范围移动微调地方,但为了避免VR的“晕动症”问题,举办长途移动时只好传送。

  • 编程](https://www.zhihu.com/question/43416744) .
    遗憾的是博客园很多答案在攻击这道题本身的不错,尽管自己不是这次的面试官,但本身觉得这是一道分外好的面试题。当然,只是道加分题,答不上,不扣分。答得正确,表明解决问题的思绪和力量要领先应届生平均水平。
    于是写下面这段,是因为我认为大部分后台服务端开发都有可能遭受这么的BUG,尽管没有赶上,这样的题目也可以刺激我们持续揣摩和总结。相当凑巧的是,我在九月份也遭遇了一个类似的还要要进一步严重的BUG,这是本人要好挖的一个很深的坑,不填好,整个项目就不能上线。
    明天一度仙逝了一个多月,趁着有时光,自己好好总计一下,希望里面涉及的一对经历和工具可以带给我们一点救助。

花大价格买了VR设备却没游戏可玩,不通晓有没有玩家境遇了如此的窘迫场合吗?先天,一款一线游玩大厂制作发行的VR游戏《毁灭战士VFR》正式发售,上架了Steam及杉果游戏等零售平台,可能会让这一题目有着革新。

AddressSanitizer的优点

address
sanitizer(简称asan)是一个用来检测c/c++程序的急速内存检测工具。相比valgrind的助益就是速度快,合法文档介绍对程序性能的暴跌只有2倍。
对Asan原理有趣味的同窗可以参考asan的算法这篇作品,它的兑现原理就是在程序代码中插入一些自定义代码,如下:

 编译前:  
*address = ...;  //   or: ... = *address; 
编译后:   
if (IsPoisoned(address)) { 
    ReportError(address, kAccessSize, kIsWrite);  
}
*address = ...;  // or: ... = *address;` 

和valgrind显明例外的是,asan需要丰富编译开关重新编译程序,好在不需要团结修改代码。而valgrind不需要编程顺序就能直接运行。
address sanitizer集成在了clang编译器中,GCC
4.8版本以上才支撑。我们线上先后默认都是利用gcc4.3编译,于是我测试时直接采纳clang重新编译nginx:

--with-cc="clang" \ 
--with-cc-opt="-g -fPIC -fsanitize=address -fno-omit-frame-pointer" 
其中with-cc是指定编译器,with-cc-opt指定编译选项, -fsanitize=address就是开启AddressSanitizer功能。

鉴于AddressSanitizer对nginx的震慑较小,所以大压力测试时也能达标上万的产出,内存泄漏的问题很容易就固定了。
这里就不详细介绍内存泄漏的因由了,因为跟openssl的错误处理逻辑有关,是自家自己实现的,没有大规模的参考意义。
最根本的是,知道valgrind和asan的行使状况和方法,遭受内存方面的题目可以高效修复。

如此这般说我们就都懂了吧?

valgrind的缺点

现身内存泄漏或者内存问题,我们第一时间都会想到valgrind
valgrind是一款特别非凡的软件,不需要再行编译程序就可以直接测试。效用也卓殊强劲,可以检测常见的内存错误包括内存先河化、越界访问、内存溢出、free错误等都可以检测出来。推荐我们使用。
valgrind 运行的基本原理是:
待测程序运行在valgrind提供的模拟CPU上,valgrind会纪录内存访问及总结值,最终举办相比和不当输出
自家经过valgrind测试nginx也发现了一部分内存方面的荒唐,简单分享下valgrind测试nginx的经历:

  1. nginx通常都是使用master
    fork子进程的不二法门运行,使用–trace-children=yes来追踪子进程的消息
  2. 测试nginx +
    openssl时,在应用rand函数的地方会唤起广大内存不当。比如Conditional
    jump or move depends on uninitialised value,Uninitialised value was
    created by a heap
    allocation等。那是出于rand数据需要部分熵,未初步化是正常的。假使需要去掉valgrind指示错误,编译时索要加一个增选:-DPURIFY
  3. 假如nginx进程较多,比如跨越4个时,会造成valgrind的失实日志打印混乱,尽量缩小nginx工作过程,保持为1个。因为一般的内存错误其实和过程数目都是一直不涉及的。

上边说了valgrind的效果和应用经验,不过valgrind也有一个卓殊大的缺陷,就是它会分明降低程序的特性,官方文档说利用memcheck工具时,降低10-50倍
也就是说,假如nginx完全握手性能是20000
qps,那么使用valgrind测试,性能就只有400
qps左右。对于一般的内存问题,降低性能没啥影响,不过自己本次的内存泄漏是在大压力测试时才可能遇见的,假诺性能降低这么肯定,内存泄漏的荒唐历来检测不出来。
只能再考虑其他措施了。

*关于“杉果游戏”:一家为国内单机玩家操碎了心的游乐代理发行平台。已与B社、卡普空、沃纳、万代南梦宫等近百家海内外厂商建立协作,致力于将生化危机、上古卷轴、辐射、蝙蝠侠、黑暗之魂等单机游戏以更打折的价钱带给中华玩家。*

core bug fix小结

结构好了上述高并发压力分外测试系统,果然,几分钟之内肯定出CORE。有了安居的测试环境,这bug
fix的效率自然就会快很多。
虽说此时经过gdb依旧不便民定位根本原因,可是测试请求已经满意了触发CORE的规范,打开debug调试日志也能触发core
dump。于是可以不停地修改代码,不断地GDB调试,不断地充实日志,一步步地追踪根源,一步步地类似真相。
说到底经过不停地再次上述手续找到了core
dump的根本原因。其实在写总括文档的时候,core
dump的根本原因是怎么样已经不太重大,最重大的仍旧解决问题的笔触和经过,这才是值得享受和小结的。很多状态下,千辛万苦排查出来的,其实是一个分外醒目依旧愚蠢的一无是处。
比如这一次core dump的要害原因是:
鉴于并未科学地设置non-reusable,并发量太大时,用于异步代理统计的connection结构体被nginx回收并拓展了先河化,从而造成不同的轩然大波中冒出NULL指针并出CORE。

core dump的调试

先是说一下core的解决思路,首假诺之类几点:

  1. gdb及debug log定位,发现功效不大。
  2. 怎么样复出bug?
  3. 结构高并发压力测试系统。
  4. 布局稳定的百般请求。

内存泄漏

即便如此缓解了core
dump,不过此外一个题材又浮出了水面,就是**高并发测试时,相会世内存泄漏,大概一个钟头500M的规范**。

8月份的时候看看一道面试题,据说是腾讯校招面试官提的:在多线程和高产出环境下,假若有一个平分运行一百万次才现身一回的bug,你什么样调节这多少个bug?果壳网原贴地址如下:[腾讯实习生面试,这两道问题该怎么回应?

gdb及debug log成效太低

因为有core dump ,所以这几个题材初看很容易定位。gdb 找到core
dump点,btrace就能清楚基本的缘由和上下文了。
core的直接原因非凡简单和宽广,全体都是NULL指针引用导致的。然而从函数上下文想不通为啥会并发NULL值,因为这一个指针在原生nginx的轩然大波和模块中都是如此使用的,不应该在这几个地点成为NULL。由于暂时找不到根本原因,仍然先解决CORE
dump吧,修复办法也非凡简单,直接判断指针是否NULL,如假如NULL就间接重返,不引用不就完事了,这些地方之后一定不会出CORE了。

诸如此类的防守式编程并不提倡,指针NULL引用固然不core
dump,而是平昔回到,那么那么些错误很有可能会影响用户的造访,同时这样的BUG还不了解哪些时候能透露。所以CORE
DUMP 在NULL处,其实是丰硕负总责和有效性的做法。

在NULL处重返,确实避免了在这多少个地点的CORE,不过过多少个钟头又core
在了此外一个NULL指针引用上。于是自己又继续加个判断并防止NULL指针的引用。正剧的是,过了多少个钟头,又CORE在了此外地点,就这样过了几天,我平昔在想干吗会见世局部指针为NULL的图景?为啥会CORE在不同地点?为何自己用浏览器和curl这样的下令工具访问却未曾其余问题?

深谙nginx代码的同校应该很明亮,nginx极少在函数入口及其余地点判断指针是否为NULL值。特别是有些根本数据结构,比如‘ngx_connection_t’及SSL_CTX等,在伸手接收的时候就做到了先导化,所以不容许在持续正常处理过程中出现NULL的图景。

于是乎我更是迷惑,分明NULL值导致出CORE只是表象,真正的问题是,那么些关键指针为何会被赋值成NULL?
本条时候异步事件编程的短处和复杂就表露了,好好的一个客户端的请求,从逻辑上应当是连接的,但是被读写及时间事件拆成了多少个片断。即使GDB能纯粹地记录core
dump时的函数调用栈,但是却无力回天精确记录一条请求完整的事件处理栈。根本就不亮堂上次是哪位事件的如何函数将这多少个指针赋值为NULL的,甚至都不知晓这多少个数据结构上次被哪些事件采纳了。

举个例子:客户端发送一个例行的get请求,由于网络或者客户端表现,需要发送一遍才成功。服务端第三回read没有读取完所有数码,这一次读事件中调用了
A,B函数,然后事件重回。第二次数据来临时,再一次触发read事件,调用了A,C函数。并且core
dump在了C函数中。那么些时候,btrace的stack
frame已经没有B函数调用的音讯了。

所以由此GDB无法准确定位 core 的的确原因

log debug的新尝试
那时候强大的GDB已经派不上用场了。肿么办?打印nginx调试日志。
然则打印日志也很烦躁,只要将nginx的日记级别调整到DEBUG,CORE就无法重现。为啥?因为DEBUG的日记消息量十分大,频繁地写磁盘严重影响了NGINX的性能,打开DEBUG后性能由几十万直线下跌到几百qps。
调整到另外级别比如
INFO,性能即便好了,不过日志音信量太少,没有帮忙。即使如此,日志却是个很好的工具,于是又尝试过以下方法:

  1. 本着一定客户端IP开启debug日志,比如IP是10.1.1.1就打印DEBUG,其他IP就打印最高级此外日记,nginx本身就襄助这样的部署。
  2. 闭馆DEBUG日志,自己在局部最紧要路径添加高级其它调节日志,将调试音信通过EMERG级别打印出来。
  3. nginx只开启一个历程和少量的connection数。抽样打印连接编号(比如尾号是1)的调试日志。

总体思路如故是在不彰着降低性能的前提下打印尽量详细的调剂日志,遗憾的是,上述办法依然不可以扶助问题一定,当然了,在频频的日志调试中,对代码和逻辑更是熟识。

特别测试请求的社团

压力测试工具和系列都准备好了,依然无法规范复现core
dump的环境。接下来还要形成很是伸手的布局。构造哪些异常伸手呢?
是因为新增的效应代码紧假使和SSL握手相关,这些进程是跟着TCP握手爆发的,所以异常也根本暴发在这个等级。于是我设想构造了之类两种分外境况:

  1. 不行的tcp连接。即在客户端tcp
    connent系统调用时,10%概率直接close这个socket。
  2. 异常的ssl连接。考虑三种情况,full handshake第一阶段时,即发送 client
    hello时,客户端10%概率直接close连接。full
    handshake第二品级时,即发送clientKeyExchange时,客户端10%概率直接直接关门TCP连接。
  3. 非常的HTTPS请求,客户端10%的伏乞使用不当的公钥加密数据,这样nginx解密时必定会败北。

分布式自动测试系统的构建

由于是HTTPS请求,使用ECDHE_RSA密钥互换算法时,客户端的测算消耗也正如大,单机也就10000多qps。也就是说假如server的习性有3W
qps,那么一台客户端是力不从心发送这么大的下压力的,所以需要构建一个多机的分布式测试系统,即由此中控机同时决定多台测试机客户端启动和终止测试。
事先也关乎了,调试效能太低,整个测试过程需要可以自动化运行,比如早上睡觉前,可以操纵多台机械在不同的协商,不同的端口,不同的cipher
suite运行总体清晨。白天因为一直在盯着,运行几分钟就需要查阅结果。
其一系统有如下效果:

  1. 并发控制多台测试客户端的启停,最后汇总输出总的测试结果。
  2. 辅助https,http协议测试,帮助webserver及revers proxy性能测试。
  3. 支撑配置不同的测试时间、端口、URL。
  4. 基于端口选取不同的SSL协议版本,不同的cipher suite。
  5. 根据URL选择webserver、revers proxy模式。

作者:helloworlds
链接:https://zhuanlan.zhihu.com/p/21348220
来源:知乎
小说权归作者所有。商业转载请联系作者拿到授权,非商业转载请表明出处。

发表评论

电子邮件地址不会被公开。 必填项已用*标注