写点什么

Heroku 危机带来的启示

  • 2013-02-21
  • 本文字数:3328 字

    阅读完需:约 11 分钟

这些日子,说 Heroku 处在风口浪尖一点都不为过,先前 InfoQ 就 Heroku 大用户 Rap Genius 的不满做了报道,虽然 Heroku 在官方博客上做了说明,但 Rap Genius 和众多网友并不买账,问题仍在延续,不妨让我们对整件事件做个回顾,看看能够从中得到什么启示。

事件回顾

2 月 13 日,Rap Genius 在其网站上发布了一篇文章,讲述了他们在Heroku 上遇到的问题,并做了分析。问题的导火线是之前为了解决一些JavaScript 的小问题,Rap Genius 在线上做了些ab 基准测试,结果却发现有些页面的响应时间远比Heroku 和New Relic 所报告的时间长。以静态的版权页面为例,Heroku 提供的平均响应时间是40ms,而Rap Genius 测试所得的时间却是6330ms。

Rap Genius 的同学在自己分析的同时,也和 Heroku 的工程师在进行沟通,最后确定问题的原因是处在 Heroku 的路由策略上,关键是 Heroku 的文档并未正确地描述其路由策略(在各个时期的不同文档中,对“智能路由”的描述都是只有在 Dyno 可用时才会将请求路由过去),但实际情况是路由采用了随机分配的策略,不考虑 Dyno 当时的情况,导致大量请求都在 Dyno 上排队,没有得到及时处理。更不幸的是 Heroku 的日志和监控并没有很好地反应实际情况。

这篇文章在 Hacker News Reddit 上一经转发,也获得了不少关注,有网友就在评论中讨论了各种路由算法。在 Rap Genius 的文章中,他们用 R 做了个模拟,原本只需 75 个 Dyno 的一个应用,使用随机路由则需要 4000 个以上的 Dyno。

面对这一情况,Heroku 的危机公关并不成功,虽然 Oren Teich(Heroku 的 GM)及时在 Hacker News 和官方博客上发表声明,承认了他们在 Ruby on Rails 应用上的性能问题,并做了一些承诺;第二天,官方博客上如约发表了具体的技术分析及后续改进的计划。但这些举措都没能让用户满意,暂且不论 3 年来为此多收的费用,至少 Heroku 并没有写出真实的情况:

  1. 模糊了本次事件的时间——Rap Genius 的共同创始人 Tom Lehman 在 2 月 5 日就已经和 Heroku 的 CTO Adam Wiggins 讨论这个问题了,而且在 2 月 8 日发给他了模拟结果,因此 Heroku 并不是在 2 月 13 日才知道这件事情的。更有人早在 2011 年 2 月 17 日就写过博文反应这个问题,还在 Google Group 里进行了讨论,Oren Teich 还亲自答复过,所以 Heroku 早就知道文档和系统实现不符合,存在性能问题。
  2. 模糊了本次事件的影响范围——Heroku 的文中只说了 Bamboo 上的 Rails 应用的性能受到影响,Tom Lehman 调侃到为什么 Cedar 的性能没有受到影响,是因为它用 Thin(Cedar 上默认的 Web 服务器)跑 Rails 的性能就没好过。

问题剖析

在 Heroku 的技术分析里详细描述了造成问题的原因。

Bamboo 是早期的 Heroku 运行时技术栈,运行于 Debian 5.0 之上,提供了两套 Ruby VM——Ruby Enterprise Edition 2011.03 1.8.7-p334 和 MRI 1.9.2-p180,只支持 Ruby on Rails 2.x,使用 Thin 作为 Web 服务器。后来,随着技术的发展,Heroku 将默认的 Bamboo 换成了 Cedar ,从仅支持 Rails 演化为了支持多平台多语言(Ruby on Rails 的默认服务器同样为 Thin)。而问题也正是从这次大的系统架构升级开始的。

Thin 本质上是单线程的 Web 服务器,基于 EventMachine 来做多路复用,通过回调实现请求的并发处理。但要让 Rails 应用充分发挥 Thin 的优势,在编写应用时也要按照 EventMachine 的写法加以修改,对所用的库也有要求。所以,不管是 Bamboo 还是 Cedar,默认情况下还是单线程的,不能很好地支持并发请求处理。如果在 Cedar 中选择 Unicorn ,那么情况则会有所不同。

因为使用 Thin 的 Dyno 无法并发处理请求,所以最初 Routing Mesh 的路由策略是选择只有当 Dyno 可用时才会将请求分配给它。但是由于 Cedar 支持多语言多平台,因此 Routing Mesh 的策略也做了调整,改为了更加通用的随机分配,暂时无法处理的请求在 Dyno 对应的队列中排队,不考虑 Dyno 的负载。对于 Java 应用,这个策略简单有效,但是对于单线程服务器中运行的未经优化的 Rails 应用,这就很成问题了。

更致命的是 Heroku 的文档并没有反映出这一变化,而监控也没能体现这一排队的耗时。原本 Heroku 打算让 Bamboo 的用户继续使用原来的 Bamboo 路由,直到他们做好准备迁移 Cedar。可惜的是随着流量的增加,Heroku 往路由集群里加入越来越多的节点,慢慢的使用新策略的节点占比越来越高,于是 Bamboo 就渐渐地出现了性能的下降。至于 Cedar 上用 Thin 运行的 Rails 应用,自打其上线起,就因随机路由策略而性能不佳,因此 Tom Lehman 的调侃也不无道理。

经验教训

本次事件,作为云服务提供商的 Heroku 有不可推卸的责任,其 CTO 和 COO 在很久前就知情的情况下,没有有效修正该问题,对用户造成了巨大的影响。对于一家云服务提供商而言,在进行大的架构升级前应该进行充分的评估及后续的追踪;在发现问题后,应该及时修正,减少对用户的影响。除了关键的技术实力,还有很多其他细节需要考虑,比如相关的文档和客户支持,本次 Heroku 在这些方面也都做的有欠妥当——文档没有正确反映实际情况,虽然 CTO 和 COO 亲自应答这一问题,但没有实际的后续动作。

在文档方面,同为 PaaS 的 Cloudfoundry 就比较透明,一方面因其开源特性,使用者可以完全了解其运行机制,另一方面有大量的材料能帮助大家更好地使用它。同样以路由机制为例,EMC 中国研究院的颜开撰写的《新版CloudFoundry 揭秘》中详细说明了其路由的实现:nginx 结合Lua 脚本,由Lua 分析请求,直接转发给对应的Droplet,转发是随机的,但是请求中增加了Cookie 信息,由此实现粘性会话,尽量将请求转发到同一个Droplet 上。正是由于这些材料,Cloudfoundry 的使用者可以更好地正确使用Cloudfoundry 的公有云。

在客服方面,好的客服能及时帮助客户解决问题,更能带给客户好的使用体验,而糟糕的客服,则有可能造成客户流失。之前,国内的盛大云因客服的问题遭到投诉,最终用户放弃盛大云,转用其他产品。可见,要做好一个云服务平台,光有技术是远远不够的

虽说使用PaaS 可以降低使用者的运维成本,无需再维护各种基础设施,同时提供适当的冗余,保证可用性。但是,这并不意味着使用者自己不需要下功夫,正确的架构必不可少,还需要一定的投入。

例如,本次Rap Genius 在路由的问题上吃亏,一定程度上也是由于其Web 请求的处理时间过长,才造成了队列中请求积压。对于耗时较长、占用资源的任务应该异步化,而非置于同步的Web 请求中,交由后台专门的Worker 处理更为合适(比如Heroku 上的Worker Dyno 就比Web Dyno 更适合这种任务)。eBay 在其分享中也多次提到了任务的异步化,可见异步化对于一个高负载高可用系统是何其重要

要在故障之初就发现端倪,良好的监控是必不可少的,虽然各家云服务提供商在其产品中都有监控功能,但用户还是应该自己定制适当的监控。除了对服务端的监控,也不能忽视了用户端的监控,如果平时就能察觉用户访问的时间存在异常,那么早就可以发现问题。百姓网在Velocity 大会上就分享过他们的经验,从用户的点击开始获取用户的真实体验。此外,还可以使用 Google Analytics ,国内的监控宝也能对站点进行有效的监控。

随着网站的不断发展,集群也在不断壮大,此时应该将故障视为常态,即使在云端,故障也是不可避免的,AWS 在过去的一年里发生的重大故障就不下三次, 2011 年那次著名的 US-EAST-1 故障甚至还让“天网”的攻击没有发生。在这方面 Netflix 就做的非常领先,他们的“猴子军团”在业内非常有名,通过日常自己制造故障来验证系统能否在真正的故障到来时自行恢复或者降级,降低对用户的影响。

对于云服务的使用者,如果要达到很高的可用度,必须在架构上就将容错和容灾纳入考虑之中,比如节点失效、网络中断、机房断电,甚至是 AWS 可用区整个故障。公有 PaaS 在这方面为用户提供了一些支持,但是在 AWS 可用区故障容灾方面应该还没有很好的支持,比如跨可用区的数据冗余,主从如何选择都是需要考虑的问题,需要用户自己来继续完善。

要做好一个云服务平台需要投入很多的精力与成本,而要用好这个平台,在其中上搭建站点为最终用户创造更多价值也并绝非易事,希望这次 Heroku 的事件能给大家带来一些启示,不知读者朋友您又有何经验可以分享?

2013-02-21 21:3313348
用户头像

发布了 135 篇内容, 共 60.2 次阅读, 收获喜欢 43 次。

关注

评论

发布
暂无评论
发现更多内容

2021-06-25 从简书迁移来到InfoQ首文

林建

《Spring Framework 系列》- IOC

公众号:程序猿成神之路

ioc Spring Framework

阿里实录:一个优秀的分布式系统该如何去设计?

Java架构师迁哥

敏捷项目管理是不是可以缩短项目周期,或者说“敏捷就是快”?

万事ONES

项目管理 敏捷开发 ONES 项目管理工具

高性能计算在人工智能(AI)智药中的应用

北鲲云

做好项目管理,项目经理应当掌握哪些技能?

万事ONES

项目管理 ONES 项目经理

带老弟做项目,凉了

程序员鱼皮

Java c++ Python JavaScript 技术

6月GitHub上star涨得最多的repo盘点

北游学Java

GitHub

5G时代,视频会议的未来

anyRTC开发者

音视频 WebRTC 视频会议

程序员的职业规划怎么做?7年老程序员的一份人生总结

学神来啦

程序员 日常 架构师

老夫整理的1000行MySQL学习笔记,等待有缘人

Java架构师迁哥

【得物技术】得物社区实践

得物技术

dubbo dubbo-go 社区 Go 语言 融合

百度智能云以端边云全面智能化的天工AIoT平台2.0打造智能物联网解决方案

百度大脑

人工智能 物联网

[译] R8 优化: 枚举的 Ordinals 和 Names

Antway

6月日更

B 站游戏技术平台微服务通用网关实践

bilibili游戏技术

微服务 openresty APISIX 通用网关

领导说PHP已经过时了,让我滚!!

网络安全学海

php 网络安全 信息安全 渗透测试 安全漏洞

解析 Nebula Graph 子图设计及实践

NebulaGraph

数据库 图数据库 子图

一矢多穿:多目标排序在爱奇艺短视频推荐中的应用

爱奇艺技术产品团队

推荐 模型 多目标

阿里巴巴出品:完美杜绝备战一个月面试10分钟,让Java面试从此不再难

Java架构师迁哥

B站收藏 12.5w+!GitHub 标星 6.6k+!这份文档拯救了我薄弱的计算机基础

Java架构师迁哥

内卷把我逼成了“扫地僧”把Github上所有面试题都整理了一遍,足足24W字!

Java架构师迁哥

敏捷项目管理实践,如何正确使用故事点预估工作量?

万事ONES

项目管理 敏捷开发 ONES

公安局情指勤合成作战平台解决方案,合成指挥调度系统

CHM源码阅读(jdk1.7)

周周

Github自爆:阿里内部SpringBoot学习笔记,学完直接进大厂

Java架构师迁哥

压缩微指令长度方法

若尘

计算机组成原理 6月日更

百度智能云在AI云服务市场四度夺魁!

百度大脑

人工智能 云服务

北鲲云:浅谈云计算与高性能计算的区别与联系

北鲲云

前端 JavaScript 获取字符串中重复次数最多的字符

编程三昧

JavaScript 大前端 数组 指针思想

有没有字节工牌,Java并发安全的根本原因都得懂

慕枫技术笔记

Java 高并发

Redis主从复制、Sentinel、集群总结

Hex

redis 后端 Redis 核心技术与实战

Heroku危机带来的启示_Ruby_丁雪丰_InfoQ精选文章