最近的 Heroku 大客户暴走风波引发了云计算领域的又一波争论。在云平台和云平台上的用户规模不断增加时,困扰了各种企业架构、互联网架构的伸缩性问题也被摆在了云服务提供商和用户的面前。
我们能从 Heroku 的事件中学习到什么?大规模的 PaaS 架构应该如何设计?如何确保及时的发现问题、响应问题?开发者如何保证自己在使用云服务的时候不被忽悠?云计算的架构设计者能否借鉴传统企业级架构和互联网架构的一些经验?
为了寻求这些问题的答案,InfoQ 从今天开始会组织一系列主题为《云服务如何面临业务增长的挑战》的虚拟座谈会。本期为第一期,主要讨论如下两个话题:
- Heroku 本次反映出来的路由系统延时问题,背后究竟有哪些方面的原因?
- 对于路由系统的架构设计与集群扩展,在座的嘉宾们有哪些思路和经验可以分享?
下面先简单介绍一下本期参与虚拟座谈会的几位嘉宾:
- 丛磊( @kobe ),新浪云平台首席架构师,骨灰级码农 + 深度技术控,负责 Sina App Engine 整体架构和技术研发。
- CodeBox( @CodeBox- 腾讯),效力于腾讯云平台。
- 杜熙( @raregogogo ),百度云平台架构师。
- 郭理靖( @郭理靖),京东商城云计算研发部资深工程师。
- 陆林青( @openshift ),效力于红帽,专注于 OpenShift 布道。
另外,本次我们还邀请了程辉( @程辉)和邓侃( @邓侃)的参与,两位在仔细研究了这个问题之后,认为这个问题看起来虽然简单,但背后的信息量却很大,需要掌握更多的信息后再进行评论。因此,我们会在本次虚拟座谈会的未来几期,或者其他更加合适的时机,再来邀请他们过来分享。
另一方面,通过一次虚拟座谈会,对上面两个问题也并不一定能产生完美的解答。根据目前跟一些嘉宾们的沟通,后续仍有更多的反馈和内容补充,因此我们决定将本次的话题延续到下周继续讨论,让真理越辩越明。
以下是本期嘉宾们的观点。
丛磊:
其实随机不是大问题,关键是要有一套良好的健康检查机制,另外对于等级用户需要做隔离。
为什么这么说呢,其实路由规则里面随机是个不错的选择,不一定非要用优先队列什么的,但问题的关键是一定要有健康检查,后端出现故障要能避开,后端出现延迟要能绕开,否则,这种随机只能被定义为不合格了。
SAE 目前日 PV 达到 10 亿,SAE 的路由实现是经过长时间高访问并发考验的,非常有效。其实路由分成两种,一类是从外到内(如 heroku 文中所指),一类是从内到外(SAE 内部叫 SocketProxy)。
从外到内:SAE 拥有一套自己开发的健康检查和 redispatch 机制,能够当后端出现故障时绕开,并在出现临时情况时通过适当的 redispatch 解决。其实健康检查是一个很大的话题,如何判断“挂不挂”,如何最快速的判断,都是一个可以深入讨论的话题。此外,SAE 目前的三个语言平台,PHP、Python、Java 在路由细节上还有所 不同,SAE Python 平台的路由规则非常像 Heroku 文中描述的智能路由,经过我们 Python 平台长时间运行检验,其实现是可靠的。
从内到外:SAE 内部所有 3 层以上的对外网络请求都是经过我们的代理(SocketProxy 服务)路由的,我们这套网络路由有以下几个特点:
- 完全做在系统内核层,无需语言 runtime 关心,支持 TCP/SSL/HTTP/HTTPS
- 可以针对目的地址的不同选择代理加速
- 拥有健康检查机制,防止阻塞
- 拥有针对来源地址和目的地址的统计、配额、限速功能,防止从内到外的网络攻击(如恶意抓站等)
最后就是,针对企业用户,需要做隔离,避免 runtime 的互相干扰,也要避免路由代理之间的互相干扰,在这方面,SAE 通过在其上运行的 2000 家付费企业积累了大量的经验。这方面以后有时间我会再详细讨论。
CodeBox:
说说我的个人观点吧,不代表公司意见。我先介绍一下我们的 PaaS 平台的类似系统的设计。
腾讯PaaS 平台CEE 处理用户请求时,是通过 TGW 和 tnginx 共同来完成 routing 和 load balance。
- 用户请求发到 TGW 的 vip 上,TGW 跟据域名和负载均衡策略,选择一台合适的 RS 机器,将请求转过去。 TGW 是工作在内核里面,本质上是个 Syn Proxy,因为要 hook 域名,所以必须自己跟客户端完成握手并处理一部分应用层数据。而不能像 NAT 代理一样透传 syn 包。 从工作原理上来讲,TGW 扫在前面可以处理一部分安全威胁,如半连接攻击等。
- RS 上的 tnginx 后再根据域名做二次转发,到应用容器里面去。 tnginx 工作在 RS 中,也就是 vm host,与 guest 中的 fastcgi 框架的通信是通过 unix socket 时行的。
- 整个过程中没有排队,硬要说有的话也是系统层面的 backlog。如果有突然的流量增加,由于监控和调试系统来扩容。
我们解决问题的思路跟 Heroku 的思路不太一样,我们一般从底层(系统层面)去解决问题,而不针对特定的语言。如我们的内外网负载均衡都是在内核层面做的,跟语言和组件无关。看讨论,似乎是 Heroku 的解决特定语言和特定架构引入了路由 + 排队系统,而排队系统的监控又不到位,请求停留在里面时间过长也没能发现。
我们的内网负载均衡也是在底层实现的,也跟语言和组件无关,提供最基础的的 ip:port 来抽象服务。
我们还是比较喜欢从底层解决问题。例如,新浪 SAE 是在 Apache 和 PHP 上做不同用户应用层面的隔离(2011 年 QCon 杭州了解到的,不知现在如何),CEE 是在系统层面用 container 做的,这也体现了我们的一贯思路。两种方式各有优缺点,没有绝对的好坏,例如在底层做会有抽象程度不高等问题。方案的选择主要看你侧重什么、擅长什么。
另,这个论文 The Power of Two Choices in Randomized Load Balancing 格调有点高雅,一堆公式,看起来很上流,虽不明,但觉厉。只是隐隐觉得有必要弄得这么复杂吗,我还是习惯走“简单粗暴,行之有效”的屌丝之路,哈哈。
杜熙:
我认为这次事件的直接原因是 Heroku 默认的 Thin 服务器是单线程的(而且是非异步)。每个 dyno 只启动一个 Thin 服务器进程,应用的并发数主要受限于 dyno 数,在高并发请求下,不管智能还是随机路由效果都有限,智能路由只是在一定程度缓解而已。此时,应用开发者有两个选择:一是接受 Heroku 的排队机制,其结果是部分请求延迟会增大(本次 case);二是花更多的钱,增加 dyno 数。不过以通常业务系统来看,并发消耗的 dyno 大多在等待 io,资源并未真正被有效利用,因此花费巨额的金钱增加 dyno 不是一个性价比高的办法。所以,Heroku 提供了切换到支持并发的 Web 服务器。看起来一直把 Thin 设置成默认服务器确实是一个错误的选择。
本质上,问题的根本原因是 PaaS 的提供者是否有能力为承载的应用提供保障。Heroku 作为一个 PaaS 的提供者,应该为开发者提供一套分布式架构的 Web App 运行环境。将很多底层细节屏蔽,从而让开发者从这些问题中解脱出来,专注于自身业务。而 Heroku 显然犯了一些错误:如给了开发者太多的选择(提供多种服务器支持,而非定制一个靠谱的),给了一个错误的推荐(Thin),没有及时的通知路由策略的变化,等等。因此,开发者需要擦亮眼睛,谨慎的选择有能力、有经验的 PaaS 提供商,而不能仅凭费用低廉。另外,必要的 SLA 独立监控也是必要的,不能仅凭提供商的一面之词。
最后说一下百度应用引擎(BAE)经验。BAE 脱胎于百度十二年来积累的大规模数据和服务处理的云计算能力,目前每天为数万个应用提供运行支撑,请求量超过 100 亿次 / 天。在如此高并发的状态下,为了提高请求的处理效率,BAE 对静态请求采用异步机制处理,动态请求采用多进程池处理。路由算法也是带智能的随机路由,会跳过繁忙或故障的后端节点。而且如果某个应用遇到瓶颈,BAE 能够自动在短时间内增加处理进程或服务器节点,这种“弹性伸缩”才是云计算真正的优势。BAE 也按照百度提供大规模搜索和在线服务的经验,对很多的底层策略和机制进行了调优,确保给应用的默认设置就是最好配置。因此,BAE 能够非常好的解决类似问题。
郭理靖:
对于 PaaS 平台,上层路由是必需存在的,每个 APP 的 Instance 是分布在不同机器上,不同 APP 的 Instance 又共享一台机器,需要路由来把发给 APP 的请求转向给具体的 Instance。Heroku 的核心问题是在于路由有问题。
我们在使用 CloudFoundry 的过程中也发现有类似的问题,目前来看 CloudFoundry 的路由做的比较简单,我们目前在做的一个工作就是把 DEA 的负载状态以及 DEA 里执行的 Instance 的状态都上报给 router,这样路由层有更多信息做更好的负载均衡。
陆林青:
对于 Heroku 的问题,作为另一个 PaaS 的代言人恐怕不便评论。不过从一个用户的角度出发,我希望 Heroku 能够开源,这样对解决问题、对项目发展都有利。
OpenShift 方面,对于来自 App 的更新、访问,利用 DNS+virtual host,实现了直接联络 node,而且对于 scaling app,用户访问的甚至不是同一个 node,大大减少了在某一个部分产生排队现象的几率。对于来自客户端(rhc,web console 等等)的管理请求,OpenShift 自带有 broker 和 proxy 来保证 HA;队列处理方面则有 ActiveMQ。RedHat 为了更加完善 ActiveMQ,已经收购了 FuseSource,所以所以这项核心技术现在也是 RedHat 主导。
OpenShift Online 目前已经有百万级的大型应用在跑,比如 cloud9.io——一个基于 Node.js 后端和 HTML5/JS 前端的在线 IDE。
其实 OpenShift 的技术和组件都是开源的,用户可以随时从 upstream 获得代码自行部署测试。这是 OpenShift Origin 的搭建文档:
https://openshift.redhat.com/community/wiki/build-your-own
这里跟 OpenShift online 用的代码有 99% 都是一致的,唯一的不同是少了一些商业的 Cartridge,比如 JBoss EAP。
还有 OpenShift Enterprise 版的部署文档,目前仍然在社区中更新,已经发布了两部分:
https://openshift.redhat.com/community/blogs/installing-enterprise-paas-part-2
其实 Enterprise 版就是很多客户期待已久的 on-premises 版。Origin 是上游代码,Online 和 Enterprise 是公共云和私有云两个不同实现。对 OpenShift 的实现感兴趣的同学,欢迎多去了解我们的文档和代码。
评论