我在Yahoo与ATS 九死一生的故事

http://www.sunchangming.com/blog/post/4667.html

去年9月,我去Yahoo后领导交给我的第一件事,就是把Yahoo内部一个过时的、已经End-Of-Life的http server换成Apache Traffic Server(ATS)。这件事情就类似于把某网站的架构从apache+tomcat变成nginx+tomcat一样,可以说非常简单。我只管更改一下安装脚本,剩下的让运维工程师去线上操作就行了。Too easy!! 然而没想到遇坑无数,我悲惨的人生就此开始。详情见下文。

100-continue导致响应慢

请见这个jira https://issues.apache.org/jira/browse/TS-1125 的Description。

调用我们服务的client service是使用C++基于libcurl实现的。而curl默认开启了一个很废柴的功能,就是当post body大于1k的时候,它会在Headers中加上"Expect: 100-Continue"。 当它收到100 continue的response header之后,它才会继续把body post过去。而ATS以及我们后端的App Server默认根本不理解这个东西,于是就导致curl一直卡在那里,等到timeout,然后才post body。

解决方法: Yahoo的Feifei Cai在2014年4月提交了一个补丁,使得ATS能够识别"Expect: 100-Continue"。该补丁已经被merge进去了。我只需要在配置文件中打开proxy.config.http.send_100_continue_response,那么ATS就会自动回复100 continue。问题"似乎"解决了。其实如果我们能说服调用方修改下他们的代码,禁用掉curl的这个功能,那么不仅能降低相应延迟(因为能减少一个RTT),而且也没有100 continue的麻烦了。可惜,不能。

本地端口耗尽

很遗憾的是,ATS与我们的backend(即origin server)之间并不是长连接,每来一个请求就需要建立一个TCP连接,每建立一个TCP连接就需要占用一个端口,于是很快就遇上了本地端口耗尽的问题。 Linux默认的time wait是180秒,也就是说5万个端口只够应对每秒270个HTTP请求。

这是一个非常常见的问题,通常有以下三种解决办法:

解决办法1: 减少time wait时间。 不靠谱,180秒是写死的,要改只能重新编译kernel。网上那些说可以通过sysctl改的,都是胡扯蛋。

解决办法2: sysctl中打开tcp_tw_recycle。 不安全。这台机器还要连接memcached等服务,而这些服务挂在VIP后面。

解决办法3: sysctl中打开tcp_tw_reuse。 可行。但是我测试发现,有轻微的性能损失。虽然很轻微,那就是因为这一点点改变,让我们项目的自动化测试中的性能测试挂掉了。领导斟酌再三,决定,不能因此而更改性能测试的阈值。所以此路不通。

实际上呢,我采用的是解决办法4: 127.0.0.x轮流用。虽然1个IP只有5万个端口,但是10个IP就有50万个端口,100个IP就有500万个端口。哈哈!我不得不为我的机智点个赞!

最后方法4使得ATS顺利上线。

上线后触发了bdb的bug

这又是一段苦痛的巨长无比的血泪史啊。我们ATS和backend是放在同一台物理机器上。上线后发现

(1). 在流量高峰期,backend莫名其妙的死掉,该进程的CPU几乎占满所有核。

(2). ATS偶尔会自动重启,大约1小时1次,伴随有core dump。

这构成了我部门2014年最大的线上故障。领导当即决定回滚,把ATS撤下,其它更改保留。其实我当时心里很冤。就好比你用apache+tomcat,然后高峰期发现tomcat CPU100%,可这关apache什么事情啊?!作为新人我心里很冤,争辩无力。总之,出问题的机器全掉格掉,重装系统,重新部署。

第二天,高峰期,backend继续死掉,死掉的依然还是昨天那些机器。这时候已经跟ATS一毛钱关系都没有了,硬盘都格过了啊……可是没想到组里还有人一口咬定就是ATS引起的,理由实在是太牵强我就不复述了。

CPU 100%这事其实并不难查,用perf看下CPU占哪了,然后打几个backtrace看看。

放两张第二天的截图。第一张是top的结果。

第一行是我们的backend server的进程。第二行是那个legacy的http server的进程(被该被ATS替换掉的那个)。

下面这张是perf top的结果。

还有pstack的结果我就不放了。

然后我认定是bdb的bug,证据已如此充分,并且我详细的解释了为什么bdb的mutex会耗费这么多CPU。但是没几个人能认同我。 :-( 依然还有人怀疑是ATS搞的鬼。

查找ATS coredump的原因

虽然ATS发生coredump只是次要原因,但是总归也是该解决的。我司有个team专门负责ATS的开发。这个问题最棘手在于,我们加载了Yahoo另外一个部门写的plugin。于是这事情就说不清楚,到底是ATS本身的问题,还是那个plugin的问题。在有的公司,这就成了两部门扯皮的事情。还好Yahoo不是。感谢ATS team的大力支持!backtrace显示,是那个插件在调用send的时候,传递给了一个无效的buffer,导致空指针异常。但是经ATS team和我一起合作分析发现,这是因为那个buffer被错误的提前释放了。当ATS收到"Expect: 100-Continue",它会准备好一个message block,填上"100 continue OK" 发回给client。当ATS收到body的时候,它会以为刚才那个答复已经发完了,所以它就会把之前的message block删掉。而实际上可能还没发完呢……

具体的技术细节可见此:https://issues.apache.org/jira/browse/TS-3285

Sudheer Vinukonda也是Yahoo的员工,ATS组的。是他去掉plugin后重现并修复了此bug。

5. fd耗尽,ATS僵死

系统监控图显示,在很偶然的情况下,ATS的fd会突然暴涨到30000万个,近乎耗尽,然后就不工作了。但是呢,ATS内部的监控又显示这个进程还活着,还能serve。这个简直比core dump还要命啊!!经我debug发现,是因为ATS的UnixNetVConnection::mainEvent函数错误的收到了VC_EVENT_WRITE_COMPLETE事件。我们使用了inception插件,所以它永远不该收到这个事件。于是我提了一个Bug Report:https://issues.apache.org/jira/browse/TS-3289 至于为什么会收到这个事件,以及如何稳定重现,我实在无能为力。

至此,我与ATS的恩怨情仇暂告一段落,下面是领导安排我在ATS的基础上开发一个基于脚本的HTTP router模块,择日再述。

我在Yahoo与ATS 九死一生的故事的更多相关文章

  1. 初识WEB:输入URL之后的故事

    1. 概述2. HTTP请求过程3. 相关性能检测及优化手段4. 浏览器的呈现过程5. 浏览器的呈现引擎6. 引用及延伸阅读 概述 为什么输入www.cnblogs.com之后敲一个回车,浏览器就会显 ...

  2. 张艾迪(创始人):创始人故事无限N个

    世界第一女孩+世界第一互联网女孩 创始人故事无限N个 全球第一互联网女孩EidyZhang艾迪.张 The World No.1 Girl :Eidyzhang The World No.1 Inte ...

  3. 初识WEB:输入URL之后的故事【转】

    转载一篇文章,分析的是浏览器输入url后所执行的一系列操作!写得非常清晰易懂,分享给大家! 作者:Jesse 出处:http://jesse2013.cnblogs.com/ 本文版权归作者和博客园共 ...

  4. Skype的故事:几乎所有风投都想投 犯罪分子洗钱必备

    Skype的故事:几乎所有风投都想投 犯罪分子洗钱必备 转载自: http://news.chinaventure.com.cn/11/7/1381032922.shtml 今年是 Skype 网络电 ...

  5. 数据分析侠A的成长故事

    数据分析侠A的成长故事 面包君  同学A:22岁,男,大四准备实习,计算机专业,迷茫期 作为一个很普通的即将迈入职场的他来说,看到周边的同学都找了技术开发的岗位,顿觉自己很迷茫,因为自己不是那么喜欢钻 ...

  6. Yahoo浮沉录

    Yahoo这一路曾经出过很多好技术 然而,任何人如果只是把 Yahoo 当作一家缺乏聚焦的企业来看也许忽视了公司内部的那些创新—偶尔甚至还有一些很好的产品创意.就拿搜索来说吧,我们说的不是付费搜索,而 ...

  7. ASP.NET_各个币种之间的汇率转换(实时)使用Yahoo汇率。

    近期开发支付平台的时候有运用到各国的实时汇率之间的转换问题,于是在往上找了很多相关资料,以下就是一些参考网址: 1.提供API接口的网站:https://www.showapi.com:这个网站有提供 ...

  8. 背后的故事之 - 快乐的Lambda表达式(一)

    快乐的Lambda表达式(二) 自从Lambda随.NET Framework3.5出现在.NET开发者眼前以来,它已经给我们带来了太多的欣喜.它优雅,对开发者更友好,能提高开发效率,天啊!它还有可能 ...

  9. iOS的ATS配置 - 2017年前ATS规定的适配

    苹果规定 从2017年1月1日起,新提交的 app 不允许使用NSAllowsArbitraryLoads来绕过ATS(全称:App Transport Security)的限制. 以前为了能兼容ht ...

随机推荐

  1. BZOJ 2431 HAOI2009 在列的数目的顺序相反 递归

    标题效果:乞讨1~n有都布置在物种的数目相反的顺序k计划数 订购f[i][j]对于前者i原子的反向排列的数j计划数 因此,我们将第一i插入的数1~i-1该装置 能生产0~i-1反向对 再就是 f[i] ...

  2. main thread starting…

    例的结果,下面的: main thread starting- Thrad 2 staring- Thrad 2 end- Thrad 4 staring- Thrad 4 end- Thrad 1 ...

  3. cocos2dx3.1-lua移植android流程

    我很懒惰,写这篇博客只是为了能够转出后,当忘记查看,所以我写了下面非常简单的内容.假设完全没有经验的学生请找另一篇文章 一.环境配置(win7): 用户变量如下面: ANDROID_SDK_ROOT: ...

  4. 【Android基础】单元测试的配置

    1.在AndroidManifest清单文件中进行配置 <application android:allowBackup="true" android:debuggable= ...

  5. css3 shadow为了实现各种漂亮的阴影效果

    <!DOCTYPE html> <head> <meta http-equiv="Content-Type" content="text/h ...

  6. 前框 (一个)zTree 从数据库树形菜单动态加载

    这些天做动态菜单使用此插件.现在有一个非常广泛的开源框架,最新QUI框架是菜单部分使用这个插件开发,因此,它是非常值获取深入的研究和探讨,通过使用非常丰富的感觉功能,己开发和编写,官网上有非常详尽的A ...

  7. 跑Java -jar somefile.jar时会发生什么(一个)

    最近阅读JVM源代码.一些想法写Blog分享.于是,他开了这么一个新课题. 第一篇文章取名字的时候让我很困惑,我代码的阅读是从Launcher開始入手的,也就是Java.exe(假设是windows平 ...

  8. android 电平信号状态识别View平局

    1.前言 级信号状态View在今天的Android系统是常见.状态的图标就很的经典,有几种状态,到了快没电的时候有些还会闪烁提示用户充电:还有的就是一些地图App的GPS信号强度的提示.Wifi信号强 ...

  9. 编写高质量代码改善C#程序的157个建议[1-3]

    原文:编写高质量代码改善C#程序的157个建议[1-3] 前言 本文主要来学习记录前三个建议. 建议1.正确操作字符串 建议2.使用默认转型方法 建议3.区别对待强制转换与as和is 其中有很多需要理 ...

  10. contentWindow,

    a>contentWindow 兼容各个浏览器,可取得子窗口的 window 对象.b>contentDocument Firefox 支持,> ie8 的ie支持.可取得子窗口的 ...