(点击上方公众号,可快速关注)
编译: 伯乐在线 - 10111000,英文:engineering.quora
http://blog.jobbole.com/113576/
【导读】:Quora 曾经在 2012 年 8 月使用了一种新的并行架构去渲染页面。相比以前, 3-10 倍的速度来渲染页面。如今,我们又对原来的架构设计做了一些改进,从而进一步提高了速度并节省了成本。Quora 工程师在本文和大家一起分享他们是如何改造的。
原来的并行架构设计服从主从模式,它的设计和参数是在生产环境中经过一系列基准测试后选定的。该设计中的主结点和从结点在不同的层级里:主结点机器我们称之为 webpara,每个结点上跑有 6 个主进程;从结点机器我们称之为 webworker,每个结点上有 6 个工作进程和一个用 C++ 语言编写的 fastrouter 进程。主进程和工作进程中的应用逻辑跑在相同的 web 服务器中,fastrouter 进程则是跑在一个用 C++ 定制的多线程队列服务器中,支持任意数据的快速入队和出队。这两层都是使用了AWS的 c1.xlarge EC2 实例,它们有 8 核和 6MB 的共享 CPU 高速缓存。
一个来自负载均衡器的请求会被分配给某个 webpara 机器中的空闲主进程,这个进程会先完成一部分的页面渲染工作,然后再把剩余的工作作为子请求通过工作结点机器上的快速路由分发给对应的工作进程。每个工作进程可以完成子请求需要的所有响应,或者是准备一部分响应并进一步将工作分配给别的工作进程,甚至是不同机器上的工作进程。最终,由原始的主进程把工作进程返回的所有子响应合并,并对客户的页面请求发出响应。因为这种分治的思想,使得我们有能力在许多不同的工作机器上并行的工作,从而快速的进行页面渲染。
不过,因为工作进程和主进程是在不同的机器上,所以所有的通信都依赖于网络。每个子请求和子响应都需要作为有效载荷在我们的 EC2 环境里跨机器进行传输。2012 年 12 月左右,我们开始面临一些规模扩展问题,尽管我们使用了这种并行的架构设计,但对于Quora的访问依然慢了下来。
我们的网络流量已经增长到足以挑战这种设计的极限 — 即使增加主结点机器和从结点机器,也依然不能很好改变这种情况。而像 Memcached 和 Redis 这样的外部服务调用也会随着时间的推移变得越来越慢。随后,我们意识到,我们的瓶颈在于网络 I/O 而不是 CPU。太多的网络调用导致了大量的上下文切换。
因此,我们不得不找到一种方法去减少网络容量和网络调用的数量,而所有的这些都不能影响到 CPU 的执行效率或是增加成本。为了达到这个目标,我们重新安排了架构的各个部分,通过几次A / B测试收集了详细的指标,并选择了可能实现这些目标的最佳配置。由此产生的架构就是我们所说的 Ultralisk。[1]
这种新的 Ultralisk 架构是由同一种机器类型组成 — EC2 的 cc2.8xlarge 实例,这种类型的机器在硬件虚拟化这一方面会更有效率(与其他的 EC2 实例类型相比)。另外,这些机器有着很高的网络I/O容量。
这个架构仍然与之前的架构一样采用主从模式。Ultralisk 架构主要的改进在于其中的每台物理机器同时拥有主进程和工作进程。所有由主进程生成的子请求都将交给同一台机器上的工作进程处理。因此,主进程和工作进程之间的通信不再依赖于外部网络。因为我们这种类型的通信是并行架构中的其他网络流量的 1.5 倍,所以这种变化使我们的外部网络流量减少了超过 60% 。主进程和工作进程之前的通信可以很简单的基于 TCP 连接或者 Unix 套接字实现。在我们的实验中,这两种实现方式的性能很接近,Unix套接字只是稍快一些。
每台物理机器上主进程和工作进程的个数是整体性能的关键。如果工作进程太少,我们就不能很好的利用并行从而导致系统变慢;如果工作进程太多,会导致太多的上下文切换。同样,在决定主进程的个数时,则需要在成本和速度之间进一步权衡。经过我们的实验,我们发现一个优化的配置是在每台物理机器上跑 6 个主进程,27 个工作进程和 1 个快速路由。CPU 的亲和性设置可以使得每个工作进程和快速路由进程跑在固定的 CPU 内核上。两个主进程共享一个核(因此 6 个主进程需要占用 3 个内核),剩下的核留给系统的内核进程,包括处理所有的 I/O中断,但并不仅限于此。[2]
这种架构减少了网络 I/O 数量和 I/O 资源的占用,从而使得外部服务的调用变得更快。下图给出了在 Memcached 调用时请求响应时间(毫秒)在 99% 分位处的改进。
总体来看,新的架构比之前的要快上 20-35%。下图给出了两种架构体系中请求响应时间在中位数与 90% 分位处的比率。
总而言之,Ultralisk 架构更快,更便宜,对网络资源的占用更少,而且比我们之前的 Webpara 架构更有扩展性。另外,现在每台机器都是相同的配置,完全与其他所有的机器独立,而我们也精确的知道每台机器每秒可以处理多少请求,所以我们可以以自动的方式来水平扩展我们的 Web 服务器。此外,这种新架构将我们需要管理的机器数量减少为原来的四分之一,从而可以更轻松的管理和部署。
我们在二月份已经把这种新架构完全部署到了生产环境,尽管我们的网络流量呈指数级增长,但目前还没有看到任何问题。一如既往,性能对我们至关重要,我们的速度和基础架构团队致力于让Quora给你更好的体验。
(作者 Nikhil Garg 是一名 Quora 工程师,并供职于速度团队)
补注:
[1] Ultralisk 是虫族最大和最强力的地面部队之一。它们非常昂贵。它们的基因物质已经经过无数次的测试和实验,而最后的可行版本只能用于虫族的幼虫。
[2] CPU 亲和性的正确设置是性能收益的关键。从那以后,我们也开始在不同层次的机器上设置 CPU 亲和性,而这样也确实带来了一定的收益。
看完本文有帮助?请分享给更多人
关注「CPP开发者」,提升C/C++技能
淘口令:复制以下红色内容,再打开手淘即可购买
范品社,使用¥极客T恤¥抢先预览(长按复制整段文案,打开手机淘宝即可进入活动内容)
近期,北京地区正常发货,但派件时间有所延长