这篇文章 主要揭秘Stack Overflow截止到2016年的技术架构。
首先给出一个直观的数据,让大家有个初步的印象。相比于2013年11月,Stack Overflow在2016年02月统计数据有较大变化,下面给出2016年02月09号一天的数据,如下:
你很难想象到.NET技术架构能够在每天6100万请求的情况下减少757小时的处理时间(相比于2013年)。这些改善既得益于 2015年早期的硬件设备升级 ,也跟软件的性能优化有极大的关系。
那么最近两年在硬件上有什么变化呢?以下为截止到目前为止的硬件列表:
为了支撑Stack Overflow运行,那需要做点什么呢?其实跟2013年相比并没有什么显著变化,只是做了前面提到的硬件升级和程序的性能优化。
现有系统一般都不会完全隔离开来,Stack Overflow也不列外。一图胜千言,下面给出Stack Overflow的整体架构效果图。本篇文章仅给出硬件整理的逻辑架构的亮点,具体的硬件细节部分将在下一篇文章详细介绍。
图1是机架A(在2015年2月升级的)的实物图片展示。
图1现在来给出主要系统的逻辑架构图,如图2。
图2
首先给出全局的通用规则:
首先,用户去Stack Overflow网站浏览就要通过Internet。为了让用户浏览网站的速度更快Stack Overflow采用CloudFlare的CDN加速。这里使用CloudFlare服务是因为它们的CDN服务器遍布全球。紧接着,用户的HTTP流量通过四大ISP提供商(Level 3,Zayo,Cogent和Lighttower),经过四台路由器。Stack Overflow通过标准的边界网关协议(BGP)来均衡所有的流量以便用户更有效率的打开网站。Stack Overflow的工程师Nick Craver建议在两个异地数据中心采用一个10 Gbps MPLS,这样在出现突发情况下可以快速的恢复和复制数据。
负载均衡使用的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的日志做到及时报警。
Stack Overflow经过负载均衡层导入流量到9台Web服务器(“primary”服务器),另外两台做网站元数据等环境管理。除meta.stackoverflow.com和meta.stackexchange.com外,Stack Overflow、Careers和Stack Exchange网站业务都在“primary”服务器运行。
在监控平台Opserver上可以看到,Stack Overflow在Web层的分布,见图3
图3更直观的看下对应的web服务器的图形展示,见图4
图4
在整体逻辑架构图上可以清晰的看到,紧挨着Web层的是服务层(部署在Window服务器Windows 2012R2上)。其有两个重要的功能:tag应用服务器(基于http.sys)和API(基于IIS)。为了提升这两个服务做了非常多的冗余,但不超过9倍的冗余。举个列子,从数据库加载所有的网页和对应的tags变化(每n分钟(当前设置为2分钟))是非常耗时的。这里只需要加载三次即可保证安全。Stack Overflow也同时在硬件层做了相关的优化。Tag应用服务是一个比较复杂的topic,这里简单说下,当你访问/questions/tagged/java就使用tag应用服务。还有所有/search和导航也都是用的这些数据服务。
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实时的推送消息(比如,顶栏的通知,投票,新的答案和评论)给用户。
Sockets服务器运行在web层, NetGain 是Stack Overflow实现的一个轻量级高性能实时的开源消息中间件。高峰期可达到50万并发的websocket连接。
下图展示的是一周websocket并发情况:
图6
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是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界最受欢迎的问答网站之,这是非常不错的。其中每项使用到的技术都进行了深入的研究并开源分享给社区,国内的公司可以从中获得一些启发。
感谢杜小芳对本文的审校。
给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ,@丁晓昀),微信(微信号: InfoQChina )关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入InfoQ读者交流群 (已满),InfoQ读者交流群(#2) )。