百科问答小站 logo
百科问答小站 font logo



维基百科的服务器架构是怎样的?是如何支撑起如此高的访问量的? 第1页

  

user avatar   antigng 网友的相关建议: 
      

不熟悉相关领域的老维基人强行答一波。首先需要澄清两个事实:

一,维基百科虽然表明上看起来访问量很高,但相比于其它排行榜顶端的网站,其实际的业务量是非常寒酸的。即使从绝对访问量上来说,当本人成为一名维基人的时候(大约是2014年),维基号称是世界第五大网站——时不时蹦出来的捐款口号都这么说的;然而到了今天(2020年7月),维基的Alexa排名早已跌出前十,目前位居第14

同时,值得注意的是,维基对实时内容的依赖程度远低于同处排行榜顶端的其它网站,它的访问量数据是有很大水分的。人们访问社交网站、自媒体网站是为了看新鲜事交新朋友,不是为了考古;搜索引擎向访问者提供的,应是最新索引的网站列表;至于电商/网购平台则更依赖实时数据——总不能一边货卖没了/下架了还向另一边的用户显示老数据说还有货吧。但是维基不一样,它是一部百科全书,关注的不是新朋友,新信息,新商品,而是知识。在维基上,最热门,访问量最大的条目也不都是编辑最频繁的条目

在英文维基百科上,访问最量靠前的条目如奥巴马,二战,美国等,往往几天甚至几周才有一笔编辑。这些条目的访问量比起首页的访问量来,又小了好几个数量级。然而维基百科的首页上有什么?有的只是固定的框架和几天/几周前我们就已经选出来/排好顺序的新条目,新闻热点涉及的条目,优质条目/图片等等,根本不存在热榜/热搜/推送/你的关注这种非常实时的东西。

以上种种导致的一个事实就是,绝大部分进入维基服务器的请求,是直接在缓存的层面上解决掉的,根本不会跟后端打交道;而大部分在缓存层面上miss/pass掉,进入后端的请求,涉及往数据库里写东西的比例又是小得可怜。根据https://grafana.wikimedia.org 上公开的实时数据:

从以上两图可见维基的服务器前端的吞吐量是在100krps的数量级上的,而进到后端的只有区区几个krps,足足小了1-2个数量级;而涉及后端的请求,绝大部分又是而不是,写操作的频率又要小上1-2个数量级,只有数十/数百rps。事实上,这样低的频率已让部分维基站点吃不消了,比如存储全语言共享的结构化数据的维基数据库(wikidata),由于其社群大量使用自动/半自动化的脚本维护内容,今年起维基的职员发现当wikidata的编辑频率达到每秒20次时,数据库主从延迟就会超过5秒

每秒编辑20次而已啊——你几时见过12306网站每秒钟卖20张票会导致数据库严重延迟而不能用的?没有吧。而12306在Alexa上的排名连前50都排不到。可想而知维基流量里的水分有多大了。

二,各维基站点的管理者,维基媒体基金会(wmf)是一家靠捐款维持运作的非盈利机构,同时也是开源运动的推动者,以及维基所使用的核心软件——用php写的mediawiki事实上的维护者。因此,维基的架构以及软件mediawiki的设计,并不总是——甚至很大程度上不是——以性能为唯一的考量目标的。对于商业公司而言,他们以改善自己网站为最主要的目标,可以说这个语言性能不行就大刀阔斧用别的语言重写,在必要的时候也不会排除使用收费软件来换取性能。但对wmf而言,这两条路子都是死路——wmf会考虑,如果我大规模重写mediawiki了,搞得和老版本完全不兼容了,那使用mediawiki的诸多小网站怎么办?mediawiki之所以如此臃肿低效(不信你可以在自家电脑上安一个试试),把所有主要的逻辑都放在一个core里边,正是为了迎合这些——占mediawiki用户绝大多数的——小网站的需求——只要装一个mediawiki就可以搞定几乎一切,而不必为了管理用户登录数据装这个、为了解析页面装那个、为了缩放图片再装一个什么东西......尽管对于大网站而言实在看不出有什么理由把“生成缩略图”和“解析页面”两个功能捆绑在一起,以至于专司生成缩略图,本质上只需要命令行调用vips的服务器也要带上mediawiki那一套根本没用的东西。

至于非开源软件/商业软件?更加是免谈。wmf对open core(即同时提供只有核心功能的开源免费的版本和功能更强大的闭源商业版本)的软件都有抵触情绪,就不说完全商业的软件了。哪个大网站会因为open core的原因把nginx从架构里清得一干二净?wmf旗下的各维基网站就会。


有了这些准备工作下面就简单介绍一下维基服务器架构的变迁。维基本身对外网暴露的主要入口就两组,一组提供(主要由mediawiki生成的)文本内容,另一组提供页面上所需要的多媒体内容。当你通过DNS查询各维基的网址(如en.wikipedia.orgzh.wikisource.org,whatever)时,dns会把你导向离你最近的数据中心的第一个入口;而当你想获取多媒体内容时则会查询upload.wikimedia.org这个网址,得到的是离你最近的数据中心的第二个入口。

这里就牵扯到维基的数据中心。实际上自始至终维基只有个位数的数据中心——和今天的大型CDN相比显然是小巫见大巫。它们可以大致分为两类,一类是边缘缓存数据中心,只提供缓存业务,不跑mediawiki等后端应用程序,也没有数据库;另一类是主数据中心,什么都有。边缘缓存数据中心以VPN与主数据中心相连。所有数据中心都以五个小写英文字符构成的串来命名,前两个字符是所在地名的缩写,而后三个字符是所在地附近机场的代码。起初维基还是小网站的时候只需几台服务器就能搞定一切。随着访问量的增加,wmf启用了数据中心位于佛州坦帕的数据中心pmtpa,以及位于首尔的yaseo,两者皆为主数据中心;随后,位于荷兰阿姆斯特丹的边缘缓存数据中心esams,DC对面弗吉尼亚州阿什本的主数据中心eqiad(取代了pmtpa),德州卡罗尔顿的热备主数据中心codfw,旧金山的边缘缓存数据中心ulsfo,以及新加坡的边缘缓存数据中心eqsin。也就是说目前wmf下边就eqiad,esams,ulsfo,codfw和eqsin五个数据中心,所有后端的业务都集中于eqiad,codfw仅作热备之用。当然为了例行检验codfw的运作情况,每隔一段时间wmf会把业务从eqiad切换到codfw,过一小段时间之后再切换回来,切换期间全维基处于只读状态不准编辑。

由此,维基各数据中心提供文本内容的入口的域名实际上是text-lb.(数据中心名).wikimedia.org,而提供多媒体内容的入口的域名实际上是upload-lb.(数据中心名).wikimedia.org。DNS把你访问的各维基域名视作别名,然后负载均衡给各数据中心的入口。当然这种做法的一个副作用是如果你的ISP对DNS动了手脚,不让查某个维基网站的域名,你完全可以通过查询诸如text-lb.eqsin.wikimedia.org之类轻而易举地绕过这样的限制

现在假设你要查看某个页面的文本,客户端通过DNS查到了IP地址,你的请求进入了某个数据中心的text-lb入口,它首先会被负载均衡到某台缓存前端服务器(cache-frontend)之上。缓存前端服务器负责缓存一些极高访问量的内容——如果你访问的是首页,那么很大概率在缓存前端服务器上就命中不往上游走了。缓存前端服务器miss之后,你的请求则会随机分配给缓存后端服务器(cache-backend)——后者负责缓存一些相对冷门,但有效时间更长的内容。经过这两步以后,90%以上的请求都已经消化掉了。如果你的请求很幸运是剩下那不到10%,它会至少再经过一道负载均衡,发往某个应用程序服务器(application server)(如果是边缘缓存中心在这一步会通过VPN把请求递交给主数据中心)。应用程序服务器提供少量静态内容(如硬编码在mediawiki里的js脚本)以及大部分由核心软件mediawiki生成的动态内容。当然mediawiki在生成内容时,会与更后边存储内容的服务器,以及一些实现其它功能的服务器交互。

而如果你要查看某个文件,你的请求会由upload-lb这个入口进入,在一路cache miss的情况下同样经过负载均衡,缓存前端,缓存后端,负载均衡,最后到达存储多媒体文件的服务器(media storage)。所以总而言之,text-lb和upload-lb后边的基本情况如下所示:

text-lb->负载均衡->缓存前端->缓存后端->负载均衡->主服务器(应用程序服务器)->数据库/其它业务

upload-lb->负载均衡->缓存前端->缓存后端->负载均衡->文件存储服务器->其它业务

这一基本架构自有维基以来从未改变过。但是在实现细节方面,近十年来的变化还是很大的,以下逐一说明:

负载均衡:无论是缓存之前的负载均衡,还是主服务器前的负载均衡,自始至终永远是LVS,没有变化过;

缓存:这恐怕是变化最大的部分。一开始,维基使用squid来完成前、后端缓存的功能。缓存前端服务器监听80端口,缓存后端服务器监听3128端口,这样前后端缓存可以设置于同一台服务器之上,一个请求如果在前端cache miss,也有一定的概率转发给本机监听3128端口的缓存后端。整个缓存层有三组服务器,一组负责text-lb后边mediawiki生成的动态文本内容,一组负载text-lb后边主服务器上的少量静态资源,一组负责upload-lb的多媒体文件。

然后到了2010年前后,出现了两个变化,一是维基开始支持https访问,二是维基推出了移动版页面。为解决https的问题,在LVS和squid缓存前端之间引入了nginx集群作ssl-termination。nginx监听443端口,接受加密请求,并将其解密以后转发给squid缓存前端的80端口,不加密请求则直接打入squid的80端口。为支持移动版页面,缓存层新增了专门缓存移动版页面的缓存服务器群,如此一来,整个缓存层就有四组缓存服务器,分别负责网页版动态文本内容,移动版动态文本内容,静态资源和多媒体文件。

2010年以后,wmf发现squid已无法满足日益增长的访问量,于是分阶段地将四组缓存服务器的前端和后端都由squid换成了varnish。varnish与squid不同的地方在于varnish主要使用内存缓存内容,而squid主要使用硬盘缓存内容。因此varnish特别胜任缓存层里缓存前端的任务——毕竟,高访问量,短有效期的内容使用内存来缓存比使用硬盘更为合适。当然这件事情的另一面是后端缓存还是以硬盘缓存更为合适,wmf还费了一些功夫让后端缓存的varnish工作在了硬盘缓存的模式之下。

到2015年左右,情况又发生了变化。首先,wmf觉得没必要为少量静态内容单独设置缓存服务器,于是把负责缓存静态内容的服务器(以及后面负责静态内容的主服务器,后文详述)取消掉了,缓存层就剩下网页版、移动版、文件三组缓存服务器。接下来,wmf响应了https everywhere的号召,开始大规模部署https:原先各维基站点既可以明文访问,也可以加密访问,在改造升级之后只准加密访问,不准明文访问。不仅如此,wmf更加激进地要求在集群内部,各服务器之间的通信也必须以https的方式进行

这就麻烦了,在当时,varnish纵然有诸多好处,但唯独有一个坏处,就是对https的支持很差,无论是上游还是下游,都不支持https通信。为此,wmf给出的解决方案是把nginx装在整个缓存层的每一台服务器之上,下游来的加密请求让nginx terminate,明文转给本机的varnish;varnish cache miss之后再明文转给本机的nginx,加密以后往上游发送。这就造就了前无古人后无来者的奇葩架构:

负载均衡(LVS)-<https>->缓存前端(nginx-<http>->varnish-<http>->nginx)-<https>->缓存后端(nginx-<http>->varnish-<http>->nginx)-<https>->负载均衡(LVS)-<https>->主服务器(nginx-<http>->原来的应用程序服务器...)->...

这么神奇的东西竟然真的用了若干年的时间。到了2018年左右,wmf决定对它进行升级。当时varnish 5已经发布有一段时间了,千呼万唤始出来,终于增加了对https的支持——不过只支持上游https通信,ssl termination依然没有支持。wmf一开始的想法是把所以varnish升级到5.0之后的版本——这样至少上面那个神奇东西里边,varnish后边的两个nginx就可以省了。可在这时候,wmf有了一些新的想法:

1. 无论是varnish还是nginx都是open core的软件,不合wmf的口味;

2. 以打补丁的方式让varnish实现硬盘缓存并非良策;

3. 如果有更加符合开源精神的产品同时支持硬盘缓存,具有类似的高性能,以及对https甚至http/2的支持,就应该用它来尽可能代替varnish和nginx。

然后他们发现还真有这种软件:Apache Traffic ServerATS。2019年,维基的缓存后端和缓存前端的ssl termination功能都迁移给了ATS,nginx自此无缘缓存层,而升级到版本5的varnish只使用内存缓存负责它拿手的缓存前端,缓存层的架构得以大幅简化:

负载均衡(LVS)-<https>->缓存前端(ATS-<http>->Varnish)-<https>->缓存后端(ATS)-<https>->负载均衡(LVS)-<https>->主服务器(ssl termination-<http>->应用程序服务器...)...

此即为今天(2020年)的情况。

应用程序服务器:一句话,自古以来就是apache httpd维基可能是目前全世界最大的、仍在主要业务中使用apache的网站了,这是怎样一种的对开源软件的偏好啊!维基大部分redirect/rewrite规则都是在apache的配置文件里定义的(比如,你访问en.wikipedia.org/会被重定向到en.wikipedia.org/wiki/M),少量的静态内容也是apache提供的。最早的时候使用apache配合mod_php,调用php解释mediawiki,生成动态内容。起初,应用程序服务器分成以下几组:

  1. 主应用程序服务器(appserver):处理除API之外(诸如 zh.wikipedia.org/w/api.之类)之外绝大部分动态文本内容的请求;
  2. API应用程序服务器(API appserver):专门处理API请求
  3. 琐细内容应用程序服务器(Bits appserver):处理少量静态内容请求;

在此之外还有三组应用程序服务器,分别是:

  1. 工作队列服务器(Jobrunner);
  2. 视频缩放服务器(Video Scaler);
  3. 文件缩放服务器(Image Scaler);

工作队列(job queue)是mediawiki的处理高开销、低实时性的作业的机制。举例而言,如果一个页面被删除,那么全站指向该页面的链接都应该由蓝色变成红色,但是如果在完成所有链接修改任务后再返回给客户端“编辑成功”的信息,就未免太耗时了。因而在提交删除操作之时,mediawiki只将所有待处理的页面加入工作队列,而不立即处理。每当有一个新请求进来,就从队列里拿出一个,处理掉。这样,高访问量的网站(理应有能力承受高负荷)这些不重要的作业就做得及时一些,而低访问量的网站这样的作业就做得不那么及时——反正看的人少也无所谓。工作队列服务器即专门处理这些任务的服务器。视频转码/缩放同样是高开销的作业,其在mediawiki内部也是以工作队列的机制完成的,视频缩放服务器即专门处理这种任务的特殊工作队列服务器。

文件缩放稍复杂一些。当客户端通过upload-lb向文件存储服务器请求文件时,文件存储服务器识别出请求的是缩略图,文件存储服务器里又这缩略图时,便会把请求发给文件缩放服务器,后者通过mediawiki调用命令行工具vips生成缩略图,返回给文件存储服务器。文件存储服务器把图存下来,再返还给客户端。最终都是用vips工具,为什么还要这样绕一大圈呢?如一开始所述,原因在于mediawiki要支持小网站,对于小网站而言,根本不需要单独的文件存储服务器,直接把图片存在跑mediawiki的服务器的目录里就行了,这种做法也不是那么“绕”。

到2012年左右,发生了一件大事,但为叙述方便放到后边去说。接下来就到了2015年前后,如前一部分所述,wmf把处理少量琐细、静态内容的流程完全并入了主应用程序服务器,取消了相应的缓存服务器和琐细内容应用程序服务器。另一方面,遵循https everywhere的精神,apache前面加上了nginx做ssl termination。(然而apache自古以来就支持https啊,这么说难道还是对性能不放心么?)此时,应用程序服务器层的架构如下:

负载均衡(LVS)-<https>->主服务器(nginx-<http>->apache 2.2+mod_php(PHP5, mediawiki))->存储

也是在2015年,wmf开始嫌php5太慢了,于是和当时诸多网站一样,转而使用了fb开发的神器hhvm。wmf是费了好大的劲才消灭了既有mediawiki中不兼容hhvm的代码,终于在2016年用上了hhvm,当时号称性能有很大的提升。当然hhvm是不能以内置模块的形式运行的,于是在启用hhvm的同时把apache升级到了版本2.4,mpm更改为worker,以fastcgi的形式与运行在本机的hhvm通信,应用层架构转变为:

负载均衡(LVS)-<https>->主服务器(nginx-<http>->apache 2.4+mod_proxy_fcgi-<fcgi>->hhvm(mediawiki))->存储

(然而nginx不直接支持fcgi么?)

接下来的事情大家都知道,就像开了一个天大的玩笑一般:性能有显著提升的php7横空出世,hhvm逐渐与php7分道扬镳,最终fb宣布停止hhvm对php的支持。wmf也被迫进行选择:是继续坚持hhvm呢,还是回到原点重拾php呢?站在wmf的立场上,你是打算让所有“小网站”们跟着你放弃php,使用hack开发么?所以结果猜也能猜到,wmf宁可让之前的工作打水漂,也要不惜一切代价回到php的怀抱中。2018年,在折腾了一通之后,维基终于还是用上了php7。当然,wmf也对fastcgi有了一定的经验,新架构中的php7是以fpm的方式和apache运行在同一服务器上的:

负载均衡(LVS)-<https>->主服务器(nginx-<http>->apache 2.4+mod_proxy_fcgi-<fcgi>->php-fpm(mediawiki))->存储

2019年底,随着缓存层nginx的停用,wmf觉得没必要为后端tls termination一个功能而继续使用nginx,干脆赶尽杀绝,使用更加开源友好、专司ssl termination的轻量化服务器envoy proxy代替nginx,于今年4月启用。今天(2020年)应用服务器层面架构如下:

负载均衡(LVS)-<https>->主服务器(envoy-<http>->apache 2.4+mod_proxy_fcgi-<fcgi>->php-fpm(mediawiki))->存储

nginx就这样彻底告别了wmf的生产环境,也是一绝。

接下来说说2012年发生的事情。要解释这个问题先要了解mediawiki的编辑方式。mediawiki采用的是wikitext这种标记语言编码、存储条目。在编辑条目时,编者需直接更改wikitext来更改页面的显示方式。相比于某度百科(抱歉,我没有更好的例子)自一开始即支持所见即所得的编辑方式,这种需要改代码的编辑方式多多少少对新手不太友好。wmf自然想引入一种能直接、“可视化”编辑条目的方式。当然,可视化编辑意味着直接更改页面的html元素,但mediawiki是以wikitext的形式存储页面数据的,这就需要把可视化编辑器更改后的html转回wikitext。那么问题来了:mediawiki将wikitext转成html的过程是丢信息的(最简单地,引用模板与不引用模板但在同一地方加入与模板一模一样的内容,mediawiki生成的html是一样的),不存在逆映射。所以别无他法,唯有在生成的html之中额外加入足以完成这一逆变换的信息才行。这就意味着需要引入新wikitext解析器

另一方面,随着html5成为标准,新的解析器理应支持html5,在2010年之时php并无好的html5库。此外wmf也知道,在长期与mediawiki作斗争的过程中,我们维基人学会了充分利用wikitext的“未定义行为”——啊,其实不能叫未定义行为,因为自打一开始到现在(2020年),都没有一套wikitext语法的规范嘛。mediawiki内置的wikitext解析器根本就不是以你书上学的编译那一套方法工作的,纯粹是正则替换再替换,把模板搞掉,链接搞掉,搞搞搞最后不知怎么的就搞出html了。wmf当然对此不满意,新的解析器绝不能如此。

当然性能还是很重要的。可视化编辑器这个项目一开始,wmf的人就打算在mediawiki的“解析器”之外另搞一个新的解析器,他们本来想用c++以php模块的形式实现的,但这显然超出他们的能力范围了,于是转而使用了当时初露头角的node.js——毕竟js不能不支持html5嘛。2012年,与可视化编辑器配套的新解析器Parsoid投入使用。维基上涉及可视化编辑器的一部分解析作业也由应用程序服务器直接转发给Parsoid处理

但是,Parsoid的引入导致维基站点上出现了“两个中央”的局面——既然wikitext没有定义,mediawiki和Parsoid谁都可以说自己是正统。此外,尽管node本身性能不错,但是其独立mediawiki的设置也意味着运行Parsoid的服务器需要与应用程序服务器进行大量通信(举个简单例子,Parsoid自己是不知道一个页面存不存在的,因此遇到页面中的链接,它需要向跑mediawiki的API应用程序服务器查询,来确定这个链接究竟应该显示成红色还是蓝色)。为了减小Parsoid的压力,2015年引入了同样由node实现的RESTBase放在Parsoid前面,来缓存Parsoid生成的html;应用程序服务器在处理涉可视化编辑的请求时走RESTBase。

终于到了2018年,wmf再也不打算同时维护两套解析器,决定将两者合并。那么是丢掉mediawiki的解析器,all in node.js呢?还是全然不顾node的优异性能,费时费力把node的逻辑用最新版本的php重新实现Parsoid呢(当然,php早就有html5的库了)。本着对小网站负责胜过那一点点性能优势的基本原则,wmf当然选择了后者。最后在2019年底wmf把Parsoid用php重新实现了一遍,并把它搬进了mediawiki的核心之中,node版本的Parsoid也就永久性停用了。当然这仅仅是把Parsoid搬进了mediawiki核心,并没有与mediawiki的解析器合并。截至今日(2020年)合并工作仍在进行中。

至于存储的部分本人太不熟悉,也就不强行解释了。最后附上今年(2020年)维基全站的架构图:

感兴趣的可以和先前的图比较一下。




  

相关话题

  作为阿里云的技术用户或潜在用户,你会不会因为月饼门重新考虑阿里云服务? 
  机械大一新生,在考虑要不要转专业,求建议? 
  什么是数字化供应链? 
  什么是数字化供应链? 
  为何某些维基百科条目中称台湾为中华民国? 
  如何看待华为云新发布的“开天”aPaaS? 
  如何看待沈逸对 Cloudflare 发表的争议性言论? 
  机器学习中非均衡数据集的处理方法? 
  HBase 和 Hive 的差别是什么,各自适用在什么场景中? 
  “大数据”已经过时了吗? 

前一个讨论
如何看待继晨风机器人后,各机器人宣布关闭?
下一个讨论
什麼是“高等華人”?





© 2024-12-25 - tinynew.org. All Rights Reserved.
© 2024-12-25 - tinynew.org. 保留所有权利