标点符(钱魏 Way)

Stack Exchange的系统架构

Stack Overflow是我最喜欢的问答网站,没有之一,原因是它能解决我学习程序过程中遇到的大多数问题,而 Quora知乎更多的是拓展我的视野。(不要和我提百度知道,百度知道是小学生用来做暑假作业的!)

目前Stack Overflow每月不重复的访问用户超过1600万;每月网页浏览量(PV)增长了近6倍,达到9500万。已经发展壮大成了 Stack Exchange Network,而这个网络包括Stack Overflow、Server Fault和Super User等,旗下总共拥有43个网站,而且发展势头良好。

Stack Overflow的变化翻天覆地,而不变的是他们开放的心态,所以才有了这篇架构分享的文章。最近,他们写了一系列文章分享他们如何应对这样的快速增长。

(期待后面有时间把上面提到的文章都翻译一遍)

在过去的一段时间里,Stack Exchange到底发生了哪些明显的变化呢?

  • 更多:更多的用户,更多的PV,更多的数据中心,更多的站点,更多的开发者,更多的操作系统,更多的数据库,更多的服务器…更多
  • Linux:Stack Overflow因使用Windows系统而著称,现在他们使用越来越多的Linux服务器,比如HAProxy(负载均衡), Redis(NoSQL数据库),Bacula(数据备份系统),Nagios(远程监控软件),日志,路由器都运行于Linux系统,几乎所有需要并行处理的功能都是由Linux处理。
  • 容错:Stack Overflow目前为两条不同的线路使用了两个不同的交换机,增加了更多的冗余服务器,将一些网站服务运行于第二个数据中心。
  • NoSQL:Redis作为整个网站的缓存层。这是一个巨大的改变,以前并没有将缓存作为一个独立的层分离出来。Redis是一个运行于Linux的NoSQL数据库。

遗憾的是,一些我关注的问题并没有从中找到答案,比如面对这么多不同的系统,如何解决多租户的问题(Multi-tenancy 是一种软件体系结构,在这种体系结构中软件运行在 software as a service 服务商的服务器上,服务于多个客户组织即 tenant)。但是,从中我们依然可以学到很多。下面是收集的一些数据列表:

统计信息

  • 每月9500万次浏览量
  • 每秒800个HTTP请求
  • 每秒180个DNS请求
  • 每秒55M流量
  • 1600万个用户(Stack Overflow的流量在2010年增长了131%,全球每月不重复访客增至1660万人)。

数据中心

  • 1个机架放在俄勒冈州的Peak Internet(用于放置chat和Data Explorer)
  • 2个机架放在纽约州的Peer 1(用于放置Stack Exchange Network的其余部分)

硬件设备

  • 10台戴尔R610 IIS Web服务器(3台专门用于Stack Overflow):1个英特尔至强处理器E5640,2.66 GHz四核,8线程;16 GB内存;Windows Server 2008 R2
  • 2台戴尔R710数据库服务器:2个英特尔至强处理器X5680,3.33 GHz;64 GB内存;8个硬盘;SQL Server 2008 R2
  • 2台戴尔R610 HAProxy服务器:1个英特尔至强处理器E5640,2.66 GHz;4 GB内存;Ubuntu Server
  • 2台戴尔R610 Redis服务器:2个英特尔至强处理器E5640,2.66 GHz;16 GB内存;CentOS
  • 1台戴尔R610 Linux备份服务器,运行Bacula:1个英特尔至强处理器E5640,2.66 GHz;32 GB内存
  • 1台戴尔R610 Linux管理服务器,用于Nagios和日志:1个英特尔至强处理器E5640,2.66 GHz;32 GB内存
  • 2个戴尔R610 VMWare ESXi域控制器:1个英特尔至强处理器E5640,2.66 GHz;16 GB内存;2只Linux路由器;5台戴尔Power Connect交换机

 开发工具

  • 编程语言:C#(ASP.NET)
  • 集成开发环境(IDE):Visual Studio 2010 Team Suite
  • 开发框架:Microsoft ASP.NET Framework 4.0
  • Web框架:ASP.NET MVC 3
  • 视图引擎:Razor
  • 浏览器框架:jQuery 1.4.2
  • 数据访问层:LINQ to SQL,一些原始SQL
  • 源码控制:Mercurial和Kiln
  • 比较工具:Beyond Compare 3

软件与技术

外部组件(一些没有包含在开发工具中的代码)

  • reCAPTCHA
  • DotNetOpenId
  • WMD – Now developed as open source. See github network graph
  • Prettify
  • Google Analytics
  • Cruise Control .NET
  • HAProxy
  • Cacti
  • MarkdownSharp
  • Flot
  • Nginx
  • Kiln
  • CDN: 没有使用,所有静态内容从sstatic.net来提供,这个快速的、无cookie的域用于将静态内容分发到Stack Exchange系列网站。

开发人员和系统管理员

  • 14名开发人员
  • 2名系统管理员

内容

  • License: Creative Commons Attribution-Share Alike 2.5 Generic
  • Standards: OpenSearch, Atom
  • Host: PEAK Internet

更多可以学习的架构知识

  • 使用HAProxy替代Windows NLB 的原因是:HAProxy成本低廉、易于使用,还是免费的;而且通过Hyper-V,很适合作为网络上的一个512M虚拟机“设备”。它还在服务器的前端工作,所以对服务器来说完全透明;而且作为不同的网络层,更容易排除故障,而不是与你的所有窗口配置混杂在一起。
  • 没有使用CDN,因为与捆绑在现有主机方案中的带宽相比,连亚马逊CDN这样“便宜的”CDN其费用都非常昂贵。按照亚马逊的CDN费率和Stack Overflow的带宽使用量,每月至少要付1000美元。
  • 备份到磁盘上,便于快速恢复;备份到磁道(tape)上,便于历史归档。
  • SQL Server的全文搜索机制集成度差,问题多,功能弱,所以改用了Lucene。
  • 最感兴趣的是HTTP请求峰值,因为他们需要确保可以处理的过来。
  • 所有站点都运行在Stack Exchange平台上。Stack Overflow、Super User、Server Fault、Meta、WebApps和Meta Web Apps都运行相同的软件。
  • 给StackExchange的用户进行区分是因为拥有不同专业技能的人不适合不同主题的站点。你也许是世界上最出色的大厨,但并不是说你就有能力修复服务器
  • 尽量把一切都放到缓存中。
  • 所有匿名用户可以访问的页面都使用缓存输出缓存输出给用户。
  • 每个站点有三种不同的缓存:本地缓存、站点缓存和全局缓存。
  • 缓存中的大部分项目在超时(通常是几分钟)后过期,但从来不被明确删除。当宣布某个特定的缓存项目无效时,他们使用Redis messaging消息传递机制,向“一级”缓存发布删除通知。
  • Joel Spolsky不是微软的忠实粉丝,他并不为Stack Overflow做出技术决策,他认为微软的协议是存在问题。需要你自己去考虑Hacker News commentor
  • Stack Overflow为自己的输入/输出系统选择英特尔X25固态硬盘组成的RAID 10阵列。这个RAID阵列消除了可靠性方面的任何问题;与FusionIO相比,固态硬盘的性能确实很好,而价格又便宜得多。
  • 微软许可证的总标价约为24.2万美元。由于Stack Overflow使用Bizspark,所以没在支付总标价,但他们能付的最多也就这么多。
  • 英特尔网卡取代了博通网卡。这解决了他们之前面临的问题:连接中断、数据包丢失和地址解析协议(ARP)表损坏。

 缓存信息

上面提到了Stack Exchange每个站点有三种不同的缓存:本地缓存、站点缓存和全局缓存。线面就来看看每个缓存的作用。

本地缓存:只能通过1对服务器/站点来访问。

  • 为了限制网络延迟时间,Stack Overflow使用了本地“一级”缓存(基本上是HttpRuntime.Cache),缓存服务器上最近设定/读取的值。这样就可以把网络上的缓存查找开销减小至0字节。
  • 缓存里面含有用户会话和等待的视图数更新等内容。
  • 缓存完全驻留在内存中,没有网络或数据库访问。

站点缓存:可以由一个站点(任何服务器上)的任何实例来访问。

  • 大部分缓存的值进入到这里,热点问题ID列表和用户验收率就是两个典例。
  • 缓存驻留在Redis(位于不同的数据库,纯粹为了易于调试)。
  • Redis的速度很快,缓存查找中速度最慢的部分就是读取字节并写到网络上。
  • 值被发送到Redis之前先进行压缩。Stack Overflow有许多处理器,大部分数据是字符串,所以得到的压缩比很高。
  • Redis机器上的处理器使用率为0%。

全局缓存:全局缓存被所有站点和服务器共享。

  • 缓存内容包括收件箱、API使用限额和另外几项真正全局的内容。
  • 缓存驻留在Redis中(位于数据库0,同样为了易于调试)。

原文链接:http://highscalability.com/blog/2011/3/3/stack-overflow-architecture-update-now-at-95-million-page-vi.html

update:2016-11-23

最近看到了Stack Overflow 2016版架构,以下为摘录的内容,与2013半对照着看相信还是可以发现很多其他的闪光点。

相比于2013年11月,Stack Overflow在2016年02月统计数据有较大变化,下面给出2016年02月09号一天的数据,如下:

  • HTTP请求数209,420,973 (+61,336,090)
  • 网页加载次数 66,294,789 (+30,199,477)
  • HTTP流量发送有1,240,266,346,053 (+406,273,363,426)字节 (1.24 TB)
  • 接收数据总量569,449,470,023 (+282,874,825,991) 字节(569 GB)
  • 发送数据总量3,084,303,599,266 (+1,958,311,041,954) 字节 (3.08 TB)
  • SQL查询数(HTTP请求)504,816,843 (+170,244,740)
  • Redis命中数5,831,683,114 (+5,418,818,063)
  • Elastic 查询次数17,158,874 (未计入2013年的数据)
  • 标签引擎请求次数3,661,134 (+57,716)
  • SQL查询耗时607,073,066 (+48,848,481) 毫秒 (168小时)
  • Redis命中耗时10,396,073 (-88,950,843) 毫秒 (2.8 小时)

你很难想象到.NET技术架构能够在每天6100万请求的情况下减少757小时的处理时间(相比于2013年)。这些改善既得益于2015年早期的硬件设备升级,也跟软件的性能优化有极大的关系。以下为截止到目前为止的硬件列表:

  • 4台数据库服务器(微软SQL Server),其中两台更新硬件配置
  • 11台Web服务器(IIS),都已更新硬件配置
  • 2台分布式缓存和消息处理服务器(Redis),都已更新硬件配置
  • 3台应用服务器(实现了tag引擎功能),其中两台为新硬件配置
  • 3台搜索服务器(ElasticSearch),配置同2013年
  • 4台负载均衡服务器(HAProxy),其中新增加的两台用于支持CloudFlare的CDN加速服务
  • 2台网络交换机(每个都是Cisco Nexus 5596 + Fabric Extenders,并升级网卡10Gbps)2台Fortinet 800C(替代2台Cisco 5525-X ASA防火墙)
  • 2台Ciso ASR-1001路由器(替代2台Cisco 3945路由器)
  • 2台Ciso ASR-1001-x路由器

下面给出Stack Overflow的整体架构效果图。下图是机架A(在2015年2月升级的)的实物图片展示。

stack-overflow

现在来给出主要系统的逻辑架构图:

2

基本规则

首先给出全局的通用规则:

  • 万事需要备份
  • 所有服务器和网络交换机要至少2 x 10Gbps带宽
  • 所有服务器配备两个电源(带有UPS电源备用)
  • 所有服务器在机架A和B上互为冗余
  • 所有服务器和服务都有异地双活(纽约机房和科罗拉多州机房)

网络服务

为了让用户浏览网站的速度更快Stack Overflow采用CloudFlare的CDN加速。这里使用CloudFlare服务是因为它们的CDN服务器遍布全球。接着,用户的HTTP流量通过四大ISP提供商(Level 3,Zayo,Cogent和Lighttower),经过四台路由器。Stack Overflow通过标准的边界网关协议(BGP)来均衡所有的流量以便用户更有效率的打开网站。Stack Overflow的工程师Nick Craver建议在两个异地数据中心采用一个10 Gbps MPLS,这样在出现突发情况下可以快速的恢复和复制数据。

负载均衡(HAProxy)

负载均衡使用的HAProxy 1.5.15和CentOS 7,并在HAProxy加入安全传输层协议(TLS/SSL)。后续会升级HAProxy到1.6版本来支持HTTP/2。

负载均衡器配备2对10Gbps网络。Stack Overflow通过加内存来有效的解决安全套接层(SSL)问题。缓存安全传输层协议(TLS)会话到内存加以重复使用,这样可以减少对于同一台客户端连接的重复计算,到达提升会话的速度和成本。况且RAM相当便宜,实现了双赢的效果。

负载均衡器的设置是相当的简单。它们监听各路IPs,并进行路由分发。Stack Overflow还做了负载均衡限流和监控HAProxy的日志做到及时报警。

Web层架构(IIS 8.5,ASP.Net MVC 5.2.3,和.Net 4.6.1)

Stack Overflow经过负载均衡层导入流量到9台Web服务器(“primary”服务器),另外两台做网站元数据等环境管理。除meta.stackoverflow.com和meta.stackexchange.com外,Stack Overflow、Careers和Stack Exchange网站业务都在“primary”服务器运行。

在监控平台Opserver上可以看到,Stack Overflow在Web层的分布:

3
更直观的看下对应的web服务器的图形展示:

4

服务层(IIS,ASP.Net MVC 5.2.3, Net 4.6.1和HTTP.SYS)

在整体逻辑架构图上可以清晰的看到,紧挨着Web层的是服务层(部署在Window服务器Windows 2012R2上)。其有两个重要的功能:tag应用服务器(基于http.sys)和API(基于IIS)。为了提升这两个服务做了非常多的冗余,但不超过9倍的冗余。举个列子,从数据库加载所有的网页和对应的tags变化(每n分钟(当前设置为2分钟))是非常耗时的。这里只需要加载三次即可保证安全。Stack Overflow也同时在硬件层做了相关的优化。Tag应用服务是一个比较复杂的topic,这里简单说下,当你访问/questions/tagged/java就使用tag应用服务。还有所有/search和导航也都是用的这些数据服务。

缓存&发布/订阅(Redis)

Stack Overflow在缓存层用Redis,Redis服务器256GB内存,采用master/slave结构部署,尽管每个月16000万的ops,每个实例的CPU使用率也在2%之下。

5
Redis所在服务器有L1/L2高速缓存,Web服务的HTTP缓存设置在一级缓存L1中,Redis缓存在二级缓存L2。当用户访问在一级缓存L1中未命中后会去二级缓存中的Redis取值,这些值以Protobuf格式存储,并以protobuf-dot-net解析。Redis客户使用的StackExchange.Redis(Stack Overflow内部实现并开源了)。如果web服务在L1和L2两级缓存都未命中,则会直接去原始数据源获取(比如,数据库查询,API回调等),然后并把获取到的结果缓存到本地和Redis中,这时其它服务未命中L1高速缓存便会去二级缓存L2/Redis中获取,节省了调用数据库查询或者API回调的访问时间。

大部分运行的问答网站都有自己的L1/L2高速缓存,通过L1缓存Key前缀、L2/Redis缓存数据库ID。

尽管Redis主要是用来缓存,但也起到一个消费和订阅的功能,Redis可以推送一个消息,然后其他订阅者来订阅消息(包括下游的Redis从库在订阅消息)。

Websockets (NetGain)

Websockets实时的推送消息(比如,顶栏的通知,投票,新的答案和评论)给用户。
Sockets服务器运行在web层,NetGain是Stack Overflow实现的一个轻量级高性能实时的开源消息中间件。高峰期可达到50万并发的websocket连接。
下图展示的是一周websocket并发情况:

6

Search (Elasticsearch)

Stack Overflow的工程师Nick Craver表示搜索层并没有激动人心的部分。在web层采用Elasticsearch 1.4,并内部实现了高性能的StackExchange.Elastic客户端,此部分代码未开源。Stack Overflow使用Elastic来查询相关的问答。

每个数据中心都有一个Elasticsearch集群,包含三个节点,每个都建有自己的索引。三个Elasticsearch集群全部使用SSD存储,192GB内存和双10Gbps网卡。

Stack Overflow使用Elasticsearch代替先前的SQL全排索引,主要因素是:Elasticsearch的扩展性和低成本。

数据库(SQL Server)

SQL Server是Stack Overflow唯一的源数据库,所有Elastic和Redis的数据都来自SQL Server。使用微软的SQL Server监控组件AlwaysOn Availability Groups部署了两个SQL Server集群。每个集群有一个主库,一个数据备份在纽约,另一个数据备份在Colorrado数据中心。所有备份是异步复制。
第一个集群硬件配置:Dell R720xd服务器,384G内存,4TB SSD存储,双12核CPU;第二个集群硬件配置:Dell R730xd服务器,768G内存,4TB SSD存储,双8核CPU。
所有数据库过去24小时CPU监控图如图7所示,大部分情况CPU使用率较低,偶尔做下缓存任务时会高些。图中NY-SQL02和04是主库,01和03是备份库。

7

纵观全文,Stack Overflow整体架构并没有采用那些非常高端的技术,却造就了一个IT界最受欢迎的问答网站之,这是非常不错的。其中每项使用到的技术都进行了深入的研究并开源分享给社区,国内的公司可以从中获得一些启发。

码字很辛苦,转载请注明来自标点符《Stack Exchange的系统架构》

评论

  1. 云飞 #1

    很好很强大了,了解了nagios的几个插件,好好研究研究!

    回复
    2012-02-15