Stack Overflow

我更愿意把 Stack Overflow 看作是能够运行于大规模数据下,但本身并不算大规模的(running with scale but not at scale)。意思是我们的网站非常有效率,但至少目前为止,我们的规模还不够“大”。让我们通过一些数字来介绍 Stack Overflow 当前是一个怎样的规模吧。以下是一些核心的数字,来自于不久前在一整天(24 小时)内的统计,准确说是 2013 年 11 月 12 日。这是一个典型的工作日,并且只统计了我们活动的数据中心,也就是我们自己的服务器。那些对 CDN 节点的请求和流量被排除在外,因为它们并不直接访问我们的网络。

  • 负载均衡器接受了 148,084,833 次 HTTP 请求
  • 其中 36,095,312 次是加载页面
  • 833,992,982,627 bytes (776 GB) 的 HTTP 流量用于发送
  • 总共接收了 286,574,644,032 bytes (267 GB) 数据
  • 总共发送了1,125,992,557,312 bytes (1,048 GB) 数据
  • 334,572,103 次 SQL 查询(仅包含来自于 HTTP 请求的)
  • 412,865,051 次 Redis 请求
  • 3,603,418 次标签引擎请求
  • 耗时 558,224,585 ms (155 hours) 在 SQL 查询上
  • 耗时 99,346,916 ms (27 hours) 在 Redis 请求上
  • 耗时 132,384,059 ms (36 hours) 在标签引擎请求上
  • 耗时2,728,177,045 ms (757 hours) 在 ASP.Net 程序处理上

(我觉得应该发表一篇文章介绍我们如何快速采集这些数据,以及为什么值得耗费精力去获取它们)

注意以上数字包括了整个 Stack Exchange 网络,但那并不是我们全部的。除此之外,这些数字也仅仅来自于我们为了检测性能而记录的 HTTP 请求。“哇,一天有这么多个小时,你们怎么做到的?”我们把这叫做魔法,当然有些人喜欢说成“许多个有多核处理器的服务器”,但我们依然坚持这是魔法。以下是那个数据中心里运行 Stack Exchange 网络的设备:

  • 4 个 MS SQL 服务器
  • 11 个 IIS 服务器
  • 2 个 Redis 服务器
  • 3 个标签引擎服务(任何针对标签的请求都会访问它们,比如/questions/tagged/c++)
  • 3 个 ElasticSearch 服务器
  • 2 个负载均衡器(HAProxy)
  • 2 个交换机(Nexus 5596和 Fabric Extenders)
  • 2 个 Cisco 5525-X ASA (可看作是防火墙)
  • 2 个 Cisco 3945 Router

有图有真相:

我们不仅仅运行网站,旁边架子上还有一些运行着虚拟机的服务器和其他设备,它们并不直接服务于网站,而是进行部署、域名控制、监控、操作数据库等其他工作。上面列表中的两个数据库服务器之前一直都是用作备份,直到最近才作为只读的负载(主要用于 Stack Exchange API),于是我们可以不需要太多考虑便继续扩大规模了。Web 服务器有两个分别用于开发和存储元数据,运行负载非常低。

核心设备

如果除去那些多余的设备,以下是 Stack Exchange 运行需要的(保持目前的性能水平):

  • 2 个 MS SQL 服务器(Stack Overflow 在一台,其他的在另一台,实际上只需一台机器运行还能有富余)
  • 2 个 Web 服务器(或许 3 个吧,不过我有信心 2 个足矣)
  • 1 个 Redis 服务器
  • 1 个标签引擎服务器
  • 1 个 ElasticSearch 服务器
  • 1 个负载均衡器
  • 1 个交换机
  • 1 个 ASA
  • 1 个路由器

(我们真该找个机会尝试这个配置,关闭部分设备,看看极限在哪)

现在还有一些虚拟机运行在后台,执行一些辅助功能,比如域名控制等等。但那都是些相当低负载的任务,我们就不做讨论了,这里把重心放在 Stack Overflow 本身,看看它是怎样全速加载出页面的。如果你希望更精确全面,可以增加一个 VMware 虚拟机进来,用于执行所有的辅助工作。这样看来并不需要很多机器,但是这些机器的规格通常在云上难以实现,除非你有足够多的钱。以下是这些“增强型”服务器简要的配置介绍:

  • 数据库服务器有 384GB 内存和 1.8TB 的 SSD 硬盘
  • Redis 服务器有 96GB 内存
  • ElasticSearch 服务器有 196GB 内存
  • 标签引擎服务器有着我们能买得起的最快的处理器
  • 交换机每个端口有 10Gb 的带宽
  • Web 服务器不是很特别,有 32GB 内存、2 个 4 核处理器和 300GB 的 SSD 硬盘
  • 有些服务器有 2 个 10Gb 带宽的接口(比如数据库),其他有 4 个 1Gb 带宽的

20Gb 的带宽太多余了?你还真特么说对了,活动的数据库服务器平均只利用了 20Gb 通道中的 100-200Mb。然而,像备份、重建等等操作,根据当前内存和 SSD 硬盘的情况,可以使带宽完全饱和,所以说这样设计还是有意义的。

存储设备

我们目前有大约 2TB 的数据库存储(第一个集群有 18 块 SSD 硬盘—— 总共 1.63TB,使用 1.06TB;第二个集群由 4 块 SSD 硬盘组成—— 总共 1.45TB,使用 889GB),这是我们在云服务器上需要的(嗯哼,又要吐槽价格了吧),请记住这全部都是 SSD 硬盘。归功于存储器良好的表现,我们数据库的平均写入时间是0 毫秒,甚至超出我们能度量的精度了。算上内存中的数据以及两级缓存,Stack Overflow 中实际的数据库读写比例是 40:60。你没看错,60% 是写操作(点此了解读写比)。此外,每个 Web 服务器都有两块 320GB SSD 硬盘组成的 RAID1。ElasticSearch 在每个区块大约需要 300GB 的容量,由于我们会非常频繁的写入或重建索引,SSD 硬盘在这里是更好的选择。

值得注意的是我们拥有一个 SAN(存储区域网络)连接到核心网络,那就是 Equal Logic PS6110X,它有 24 个可热交换的 10K SAS 磁盘和 2 个 10Gb 的控制器。这个设备仅仅被 VM 服务器用作共享储存空间以保证虚拟机高度的可用性,但并不实际支撑网站的运行。换句话说,如果 SAN 挂掉了,在一段时间内网站甚至无法察觉(只有虚拟机中的域名控制器能感知到)。

整合到一起

这所有的设备在一起是为了什么?性能。我们需要很高的性能,这是一个对我们来说很重要的特性。所有站点的首页都是问题页面,我们内部把它亲切地称作 Question/Show(路由的名字)。在 11 月 12 日,这个页面平均渲染时间是28 毫秒,而我们的要求是至多 50ms。为了使用户获得更好的体验,我们尽一切可能缩短页面加载的时间,哪怕只有一毫秒。在和性能有关的问题上,我们所有的开发人员都是“锱铢必较”的,这也有助于我们的网站保持快速响应。以下是一些 Stack Overflow 上热门页面的平均渲染时间,数据还是来自于前面统计的那 24 小时:

  • Question/Show: 28 ms (2970 万次点击)
  • User Profiles: 39 ms (170 万次点击)
  • Question List: 78 ms (110 万次点击)
  • Home page: 65 ms (100 万次点击) (这对我们来说已经很慢了,Kevin Montrose 正在着手修复这个问题)

凭借对每一次请求的时间线的记录,我们能够准确观察到页面加载的过程。我们需要这样的数据,否则难道靠脑补来做决定吗?有数据在手,我们就可以这样监控性能:

如果你对某个特定页面的数据感兴趣,我也很乐意发布出来。但这里我重点关注渲染时间,因为它表示我们的服务器需要多久来生成一个网页。网络传输速度是一个完全不同的话题了(尽管不得不承认它也有很大的关系),不过将来我会讲到的。

增长空间

非常值得一提的是我们这些服务器运行时的使用率都非常低。比如 Web 服务器的 CPU 平均使用率为5-15%,内存只使用了 15.5GB,网络流量只有 20-40Mb/s;而数据库服务器 CPU 平均使用率为5-10%,使用了 365GB 内存,以及 100-200Mb/s的网络。这使我们能做到几件重要的事情:在网站规模增大时不至于需要马上升级设备;当出现问题时(错误的查询、代码以及攻击等等,无论是什么样的问题),我们能保持网站始终不挂;在必要的时候降低功耗。这里有个我们 Web 层的监控项目:

利用率如此之低的主要原因是高效的代码。尽管本文的主题并不是这个,但是高效的代码对挖掘服务器的性能也有着决定性的作用。做一件非必要的事情所损失的,居然比无所作为还要多——把这引申到代码中就是说,你需要把它们改进得更高效了。这些损失或者消耗可以是能源、硬件(你需要更多更快的服务器)、开发人员理解代码更困难(平心而论,这个有两面性,高效的代码并不一定那么简单),以及缓慢的页面渲染——可能导致用户更少地浏览网站其他页面甚至再也不访问你的网站了。低效率代码带来的损失可能比你想象的大很多。

现在我们了解了 Stack Overflow 运行在怎样的硬件上,下次可以讨论一下为何我们不使用云。

via: blog.jobbole.com