一年一度的春晚再次落下帷幕,而微博也顺利地陪伴大家度过除夕之夜。
谈及马年春晚,人们首先想到的不是春晚上精彩的节目,而是微博上的吐槽,边看春晚,边刷微博,边吐槽,已经成了国人的习惯。看春晚不再是为了看节目,而是为了能够在微博上吐槽,知道大家在吐槽什么,更有人戏称不是春晚成就了微博,而是微博拯救了春晚。
马年春晚又格外引人注目,不仅仅是因为冯小刚亲自坐镇,担当总导演,更值得一提的是本届春晚首次将社交平台作为其与观众互动的主要途径,而新浪 微博更是成为官方二维码独家合作方。在节目播出时,用户通用手机客户端,扫描屏幕右下角的官方二维码,即可参与春晚的话题讨论。不仅如此,参与讨论的观 众,还可以免费获得微博红包,抽大奖的机会。如此一来,大大的提升了微博的活跃度瞬间提升,同时在线人数翻了几倍,给微博系统带来前所未有的访问压力。
根据以往统计的数据,春晚期间微博的访问量将激增到日常水平的数倍之多,而瞬时发表量更是飙升数十倍,如此场景丝毫不亚于淘宝双 11 和 12306 抢票时的”盛况”。
而最后的统计数据结果表明,马年春晚直播期间,微博的访问量和发表量都再创新高,而我们系统也自始至终平稳运行,经受住了此次高峰的考验。这成功的背后,是我们的工程师将近一个月的努力。其间面临了哪些问题,又是如何解决的呢?下面,我们一一为大家揭秘。
挑战1:如何应对数倍于日常访问量的压力?
每年春运抢票时,12306 都会崩溃;淘宝双 11 时,也会有短暂的购买失败的情况。究其原因还是,有限的服务器资源难以承受上千万人同时在线访问。同样,春晚的时候,微博的访问量也会激增,同时在线人数 到达日常的数倍之多。面对突然增长的访问压力,大部分互联网公司都会临时扩容来加以应对,同样我们也需要进行扩容。那么如何进行扩容?哪些部分需要扩容? 具体扩容多少?这都是厄需解决的问题。
需要提到一点的是,微博目前线上部署了几千台服务器,来保障日常的正常访问。假如面对原来数倍的访问压力时,如果简单粗暴通过线性扩容来应对的 话,需要部署原来数倍的服务器,也就是需要上万台服务器。无论从硬件成本还是从管理成本上,这都是不可接受的。那么,又该如何做呢?
在线压测,找极限,最小化扩容前端机
众所周知,为了尽可能的保障线上运行的服务器的稳定,资源都是有一定冗余度的,一般安全值在 30% 以上。在面临 5 倍的访问量时,出于成本的考虑,单纯的扩容难以令人接受。这个时候,就要充分利用每台服务器,在不影响业务性能的前提下,使每台服务器的利用率发挥到极 限,可以极大的降低资源扩容的数量。如何评估服务器的承受极限是其中的关键,为此我们在业务低峰时期,对线上的服务器进行了实际的压测。具体方法如下:
假如线上一个服务池里有 300 台 tomcat 服务器在提供 API 服务,正常情况下,每台服务器的负载都小于1(为了简化模型,我们这里只提到了系统 load 这个指标,实际情况要比这个复杂的多,还要考虑 CPU 利用率、带宽、io 延迟等)。通过运维系统,我们以 10%、20%、30%、40%、50% 等比例逐步将该服务池里的 300 台 tomcat 机器 503,通过观察一台 tomcat 服务器的负载以及 API 服务的接口性能,当服务器的负载达到极限或者 API 服务的接口性能达到阈值时,假设此时服务池里正常状态的 tomcat 服务器的数量是 100 台,那么我们就可以推断出该服务池,极限情况下可以承受 3 倍与日常的访问压力。同理,为了承担 5 倍的访问量,只需再扩容一倍机器即可。
挑战2:如何应对瞬时可达几万/s 的发表量?
互联网应用有个显著特点,就是读多写少。针对读多有很多成熟的解决方案,比如可以通过 cache 来缓存热数据来降低数据库的压力等方式来解决。而对于写多的情况,由于数据库本身写入性能瓶颈,相对较难解决。
微博系统在处理发表微博时,采用了异步消息队列。具体来讲,就是用户发表微博时,不是直接去更新数据库和缓存,而是先写入到 mcq 消息队列中。再通过队列机处理程序读取消息队列中的消息,再写入到数据库和缓存中。那么,如何保证消息队列的读写性能,以及如何保证队列机处理程序的性 能,是系统的关键所在。
按消息大小设置双重队列,保证写入速度。
众所知之,微博最大长度不超过 140 个字,而大部分用户实际发表的微博长度都比较小。为了提高写入消息队列的速度,我们针对不同长度的微博消息,写入不同大小的消息队列。比如以 512 字节为分界线,大于 512 字节的写入长队列,小于 512 字节的写入短队列,其中短队列的单机写入性能要远远高于长队列。实际在线结果表明,短队列的 QPS 在万/s 级别,长队列的 QPS 在千/s 级别,而 99% 的微博消息长度均小于 512 字节。这种优化,大大提高了微博消息的写入和读取性能。
堵塞队列,压队列机极限处理能力。
为了验证队列机处理程序的极限处理能力,我们在业务低峰时期,对线上队列机进行了实际的压测,具体方法如下:
通过开关控制,使队列机处理程序停止读取消息,从而堵塞消息队列,使堆积的消息分别达到 10 万,20 万,30 万,60 万,100 万,然后再打开开关,使队列机重新开始处理消息,整个过程类似于大坝蓄水,然后开闸泄洪,可想而知,瞬间涌来的消息对队列机将产生极大的压力。通过分析日 志,来查找队列机处理程序最慢的地方,也就是瓶颈所在。
通过两次实际的压测模拟,出乎意料的是,我们发现系统在极限压力下,首先达到瓶颈的并非是数据库写入,而是缓存更新。因此,为了提高极限压力下,队列机处理程序的吞吐量,我们对一部分缓存更新进行了优化。
挑战3:如何保证系统的可靠性?
无论是发微博,还是刷 feed,在微博系统内的处理过程都十分复杂,依赖着各种内部资源和外部服务,保证系统的可靠性显得尤为困难。
为此,我们内部开发了代号为试金石——TouchStone 的压测系统,对系统的可靠性进行全面检测。
首先,我们对微博的各个接口进行了服务依赖和资源依赖的梳理,并针对每个服务和资源定义了相应的 SLA 和降级开关。然后,模拟资源或者服务出现异常,再来查看其对接口性能的影响。以 redis 资源为例, 假设系统定义了 redis 的 SLA 是 300ms,相应的端口是 6379,通过 TouchStone,使该端口不可用,从而模拟 redis 资源出现异常,然后验证依赖该资源的接口的性能,确保 SLA 。同时,通过降级开关,对该资源进行降级,验证降级开关的有效。
基于以上方法,对系统进行了全面的检测,并对各个服务和资源的 SLA 和降级开关进行梳理,总结成业务降级手册,保证在出现问题时,运维人员无需开发的介入,也能第一时间根据降级手册进行降级,确保问题能够尽快解决。
挑战4:如何保证核心系统的稳定性?
任何一个系统,都包含核心系统和非核心系统。在出现异常的情况下,弃车保帅,只保障核心系统的稳定性也是可以接受的。
为此,我们降核心接口和非核心接口拆分,部分部署到不同的应用池子当中,确保非核心业务不会影响核心业务。比如发微博和刷 feed 属于核心业务,而评论,赞属于非核心业务,所以两者应当部署到不同的应用池中。在评论或者赞出现异常时,发微博和刷 feed 就不会受到影响,从而保障系统核心业务的稳定性。
同样,对于一个业务,也要区分核心逻辑和非核心逻辑。以发微博为例,更新缓存和写数据库属于核心逻辑,而给其它业务部门推送数据则属于非核心逻辑。因此,可以将推送数据进行异步化处理,交给单独的线程池处理,在出现异常时,不会对更新缓存和写数据库造成影响。
挑战5:如何做到异地容灾?
近些年来,异地容灾成为全球性互联网企业面临的难题之一。无论是在国内,以微信为例,还是在国外,以 twitter 为例,都曾经出现过全球性宕机的事故。由此可见,异地容灾仍旧是一个挑战。
微博早在 2010 年就开始了多机房的部署,如今已经具备三大机房(分别针对联通、电信和海外用户)。
由于人为或者天气等不可抗拒因素,网络故障近年来时有发生。微博的三个机房,各自独立承担了一部分用户的访问。在一个机房出现故障或者压力过大 的时候,通过 DNS 切换等手段,将流量迁移到另外两个机房,从而确保该访问该机房的用户不受影响。一个现实的情况例子,在马年春晚直播期间,由于观看人群的地域分布的特点, 出现了联通机房的访问量突增,同时在线人数的增长超过了电信机房和广州机房,我们通过切换一部分联通机房的流量到电信机房,使得联通机房的负载降到了安全 值的范围。
挑战6:如何实时监控系统状态?
我们都知道,地震的发生都是有前兆的,比如一些动物的异常反应。同样,系统中的任何问题出现之前,也是有线索可寻的。这就需要对系统的关键指标做实时的监控,当指标出现异常时,能够第一时间发出报警信息。
为此,我们基于实时流处理系统 Storm 开发了一套监控系统——dashboard。有别于以往的监控系统,它能实时处理系统产生的海量日志,绘制出更加直观的曲线,方便运维进行管理。通过 dashborad,我们能够了解系统的实时状态,主要包括 feed 的访问量、微博的发表量、队列机的处理性能,消息队列的堆积量等指标。当某个监控指标出现异常时,能够第一时间在 dashboard 中反映出来,从而第一时间采取措施,解决问题,避免问题扩大化。
后记
春晚已经过去一个月了,渐渐成为回忆。但春晚背后,我们的工程师所付出的巨大的努力所产生的价值,却是一笔宝贵的财富,希望这篇文章能给大家带来启发甚至帮助,也在此向为微博春晚默默贡献的工程师们致敬
转载:http://flycars001.iteye.com/blog/2031154