10个互联网团队应对高压的容量评估与高可用体系:私董会1期
导读:高可用架构关注技术架构深度实践,关注业界普遍关注的问题,关注行业发展方向。我们以私董会的形式,连接各个领域专家及行业领袖,6 月 25 日,高可用架构第一期私董会邀请了 10 家互联网技术团队负责人,讨论互联网高压场景下普遍关注的一个议题:容量评估与压力测试。
高可用架构私董会是一种闭门交流的会议,仅面向高可用架构后花园、受邀请嘉宾及少量高可用架构成员参加。加入高可用后花园可获取各期私董会讨论全文内容,参看文末说明更多了解。本文是其中 3 个互联网团队分享的实践经验,供读者参考。
京东商城核心交易系统的全流量压测
杨超 京东商城架构师
我叫杨超,2011 年加入京东,这期间订单从几十万做到了几千万。刚才大家说了很多方法,我们这边有一些场景跟大家不一样,比如京东商城的流量峰值一分钟能到几千万,如何保证系统能够应对压力及峰值?
首先要考虑的是 IDC 机房的物理容量是否足够,这是第一关。
其次是要考虑负载均衡:HA、LVS、F5 是否能负载?峰值流量几十 G 的时候能不能保证服务还活着。在活着的前提下才能考虑全链路压测的问题。
存储层(数据库和缓存)的压测方法: 首先 Redis 单机负载和整个集群的负载要有一个整体的规划。集群能承受的总量并不能等于单机负载放大的倍数,因为损耗相当严重,我们曾经出现过问题,比如联通、电信或第三方的世纪互联的网络服务瘫痪,只能从机房入口处就切断,做容灾。
针对服务集群做压测,我们有一套自己的评估方法,每一台服务器一分钟能扛多少量,一台往下有 80% 的递减,一台一台往下递减。以我们的压测经验来看并不是服务器越多越好,也不是越少越好,而是基于当前应用,压测到一个最优的配置。配置包括连接数、超时设置、RPC、数据库、缓存、服务器数量等,直到试出符合预期的数据。
从 IDC 入口、IO、业务逻辑缓存、物理存储,评估哪一层可能会出问题。首先要保证数据库不挂、Redis 数据不挂,那么在做容量压测时需要测出一个极限值。一旦接近这个极限值,就拒绝掉当前请求,当然保护之后就是有损服务。
在前端可以借鉴 12306 的处理方式,在后端处理不过来的情况下,由前端维持住,用户在页面上处于加载状态 60 秒后才返回结果,好处是让用户觉得系统是在处理过程中。这是以时间去换取响应的成功率的方式实现的,简称以时间换空间。但是我们大多数的做法是空间换时间,指在服务端把响应的时间尽量压缩,服务实例部署越来越多,容量越来越大。
另外还有突发流量的问题,我们各种参数也必须及时进行调整。比如容量从 500 万直接到 1800 万,连接数创建不及时有可能引起前端服务雪崩。但是创建连接要时间,这期间也可能会引起自动化机器宕机。那怎么做到在一两秒钟或者更短的时间内把量撑起来呢?从前往后推的做法是先活跃一两个把容量挡在前面,不要透到 Redis 和 MySQL。把前面的数据触发了以后,再从后端回原往前推。假如容灾服务层有 10 台,真正到 Web 层可能有 100 台,到 LVS 层可能就有 5 台,呈漏斗状,中间容量很大,后面的容量减少,前面大容量就先做保护。
中间的容量控制住以后,从前开始往后推,入口一旦放开,在短时间内单秒处理请求增加,增加后将产生生态循环(在单位时间内处理的请求越多,商品被预热的越快,容量就会越大),这样就会进入良性循环。
如何模拟瞬时千万量级的并发?
我们开发了专门的压测工具。目前用的是一些脚本和工具。单台发起量有限,所以采用集群,几十台或几百台机器针在同一秒钟同时起来,把量一下冲上来,就能让容量瞬间打响。比如我们找流量大的应用,把从这个应用中的请求按照比例转化成参数。因为是根据实际数据转化过来的,所以比例是正常的。类似正常用户访问,CSS、JS 各方面有请求,就和真实一致的请求,刷下来有长的短的。
其实我们在线下压测也是只压单台的,在京东交易平台的线上环境,从用户看到的价格到页面所有的动态数据,基本上 90% 都在我们部门这边。全链路的场景我们做的是线上压测。
线上压测怎么做数据隔离?
改变程序结构。我说一下为什么要这么做,当流量达到百万以上时,测试环境无法提供这么庞大的资源去做测试。直接在线上测风险也很高,随时可能引起宕机。这就需要架构师和开发人员提起 100% 的决心。首先在压则之前要梳理整个架构,预测一下压测时会穿透哪些地方,排查可能出问题的地方,把机器先隔离出来、流量切走。数据库这块是把线上几十个库先摘下来,数据存到另一个地方,或者把几十个数据库空出来在凌晨某个点更新、压测。直接落在线上库的数据测完后会用程序清掉。
如果从头设计一个系统的话可以将压测的情况考虑进去。比如在程序上做一些兼容,标记所有测试数据,让程序逻辑知道这个测试数据。这样就可以直接压测又不用担心数据会花掉。
我们压测团队总结一句话,千万不要为了压测而压测。必须以提高真实环境的系统性能为目的,不是为了压这个数据给领导看,目标是要提高我们软件的质量。
怎么把线上真实的流量和测试的流量做隔离?
互联网企业接入流量都是从前端的 LVS 过来。LVS 是流量转化机制,负载均衡各种协议,后面才是我们自己应用的程序。我们把这一部分机器摘出来,在前面架设一套 LVS 和 HA,这样过来流量就不受影响。一层一层隔离开,先压前端,再压后端。
全链路压测,一年可能就两次,618 和双十一。每次压测的数据真正写到数据库,确实会耗费很大的精力。删表会引起服务器的弹动,包括删数据时 CPU 一下就到 90% 以上,所以在做之前要提前考虑到整体的应对策略。
同时我们需要模拟几十个 G 的真实流量,除了用 LVS 和 HA。我们还有请外面团队帮我们打数据,同时我们自己内部团队也打了很多数据。要达到这种量没有可模拟的方法。淘宝跟我们的机制不同,我们要尽量做的接近真实情况才能知道线上系统的真实负载。几十台机器能承受多大量,几百台机器承受多大量,承不住就拒绝。
怎么实现在前端 Hold 住请求不降掉?
我曾做过京东在线客服的聊天工具。实现方式就是模拟的请求,放入到 MAP 一个容器里面维持住,直到处理完成 flush 出去。在前面维持住,后面服务器跟连接层分开处理。
刚刚说做在线客服,腾讯原来是 60 秒访问一次,阿里淘宝他们是 15 秒还是 30 秒会有一个请求过来,请求没收到数据就 Cache。
应对突然增长的流量时是否能做到自动化扩容?
真正自动化不多。后端把数据导到集群,多个集群分开。突发量特别大分到一个集群,平稳量分到一个集群。区别是平稳量备的灾备机器比较少。
如果前端流量突增,就打到很多备机的另外一个集群上。并在 Java 层、应用层、Web,业务逻辑层都做容灾,一旦异常就到另外一个集群。SDK 逻辑接口跳到另外一个存储或者另外一个地方去访问这个数据,如果在 Web 层,跳到另一个集群返回。
以前也出现过突发流量的情况,只能把部分功能降级,降级完跑热之后再慢慢恢复。这么大的集群也出现过崩溃,崩溃之后几个小时都很难恢复,IDC、LVS 和 link 这一层一起瘫痪。
微博的平台稳定性演进
李庆丰 新浪微博研发总监
高压力下动态扩容,实际上解决的是容量问题。系统容量不够就需要扩容。微博的服务大部分实现了 Docker 容器化部署,动态扩容可以做到 5 分钟上千台的效率。所以问题的关键在于什么时间进行扩容,也就是如何判断容量不足了。
对于容量压力的问题一般分两个层面:
一是系统层面,内存够不够?CPU 够不够?IO 是否到达瓶颈,这是运维通过系统级的监控来做;
另一个是服务应用层面,比如 CPU 和内存都 OK,但应用级别 QPS 跑不上去,支撑不了,耗时就增加了,报错增多了。
相应的我们对于容量的评估也是从两个方面进行:一是系统负载的监控判断依据;二是服务应用级别的判定依据。微博在这两个方面监控都有,但是我们更多关注的是服务应用方面,因为它最直观反应服务情况。通过监控 QPS 和接口耗时,超过阈值或者报错增多了之后,就需要做相应的扩容。
业界很多是通过系统负载来做的,但通过我们实践经验来看,系统负载和应用级别还是有很大差别,整体扩缩容的判断是靠监控服务应用级别的接口的耗时、QPS等等,一旦有异常,除了快速扩容之外,也可以先采取限流或者降级之类处理措施。
怎么判断真实容量?
主要依据监控体系和提前做压测来了解服务的大致容量情况。最早我们曾经也跟大家宣讲过 touchstone,从线上拷贝真实流量进行模拟。容量异常主要有两种情况:一种情况是流量上升,要模拟线上环境大流量时的下行流量;另一种是模拟后端资源延迟。在真实线上服务器压测的做法是缩减机器,在流量低峰时,将原 100 台集群缩减到 50 台,逐步递减看服务器的表现,直到测出临界值再加把节点加回去就行了。数据库跟缓存模型比较简单,就是将某一台机器的流量放大几倍去压。
整个测试过程都在线上环境压完成,包括缓存。我们一般会对 QPS 和接口耗时设置一个有 buffer 的阈值,比如 feed 的某个接口设置 200 毫秒的阈值,到 150 毫秒就会报警,到 200 毫秒扩容已经做完了。我们真正的扩缩容用云的方式,微博的服务都是容器化的,我们内部实现了一个 DCP(Docker Container Platform)系统用 Docker 和公有云来应对这些峰值非常方便。线上已经用的 feed 的场景,如大家都知道微博在晚高峰有非常高的峰值,就是采用公有云的资源做应对。
自动化弹性伸缩
除此之外是看监控图,一开始用手动人工的方式,看到请求峰值高了再通过手动操作把资源扩上去。现在我们变成定时扩容,因为每天的峰值时间都是差不多的。现在在做在线容量自动评估体系,在设定几个阈值之后,发现那个阈值到了,让系统自动代替人手工去自动扩容。
其实大部分的场景都是可预知的,比如每天的晚高峰,春节元旦峰值。也有突发的、不可预知的情况,比如突然哪个明星曝了一个丑闻事件导致流量立刻上来了。自动在线容量评估系统对这种突发流量场景会非常合适,依赖流量应用的性能跟报错增加,自动进行扩容。我们现在只是小范围尝试,没有全量上,因为真正操作起来是很复杂的,可能会有误差或其他别的情况,需要很精细的评估,需要后续实践一下。
存储层的扩容方案是如何实现的?
目前来讲更多的瓶颈一般都是在前端机、应用服务器。当然,在缓存跟数据库的层面我们用 Cache Service 组件来解决缓存层面的压力。对于 Java 应用在数据资源层面真正做扩缩容还是比较麻烦,因为一般都是基于连接池的。我们用 Cache Service 解决缓存层面的扩缩容。微博有一个特点是缓存的命中率非常高都是 99% 以上,大部分压力在缓存层面就都解决了,数据库层面扩容目前不是很紧迫。
我们在缓存做了两到三层的保障,分层和主备。因为微博流量太大,不用缓存数据库资源成本太高,所以我们必须保证缓存不能出现问题,万一有问题我们通过降级的手段来解决,然后再把它顶上去。为了解决缓存预热慢的问题,还采用了多层缓存,还有 Master-Slave,保证不会大量穿透到数据库,缓存也很容易热起来。
压力过大的时候,我们在缓存上有类似 CPU L0、L1 的概念,可以理解成高效的 LRU 层缓存,只要加进去,就能扛更多的流量。热点通常是比较集中,如果这个压力过大,通常是 Cache 资源本身的 QPS 撑不住了,这时候增加一些节点充当 LRU 层,它马上就可以热起来,我们叫 L1 层缓存。
全新的服务怎么评估容量够不够,比如以直播为例,需要布多少台机器?
容量主要还是看业务场景的瓶颈点。以直播为例,它最大的瓶颈是在消息下推的量。消息下推一般用长连,瓶颈就看单机可承受的最大连接数。直播的场景的消息服务是有很多客户端建立一个长连接到服务器,每个用户一个长连接。具体主要可能瓶颈有2个:第一,每台服务器可支撑多少长连接,第二,每台服务器可以下发多少消息,因为直播场景相当于一个大群,一个人发言要给所有在线群成员推消息,现在一个热点直播房间都是几十万,想想这个消息下发量会有多大。
根据运营场景的评估,说我们直播峰值大概会有多少用户在线,活跃程度大概什么样子,也就是预估下每秒消息下发峰值。然后在根据这些峰值除以单服务器可以承受的量,就是需要服务器的数量。
比如具体到直播这个场景,如果单机长连接最大支撑 2W,预估的最高在线用户数除以 2W 就可以得出所需服务器数量。
对于消息下发,公有云很多会有 pps 的限制,也就是每秒下发包数量有限制,用预估的发消息数除以单机 pps 阈值,也可以得出所需服务器数量。然后综合一看就知道整体需要多少服务器了。
更重要的是,对于这些瓶颈和问题,我们的做法是先从理论上进行预测,然后模拟场景压测。比如在测试环境中建立多少连接,下发的包数提上来之后,对于监控图上的指标跟我们的预期是否一致,如果一致证明没问题,服务器的数量评估是准确,其它有问题再具体分析。
也就是说,具体瓶颈点是什么,是多少,要根据具体业务来确定,根据业务场景瓶颈来决定用多少台服务器。
百度贴吧的容灾体系
曹建栋 前百度贴吧架构师
原先贴吧是跑在私有云上面,容量评估最终的目标要不就扩要不就缩,扩跟缩要分两方面:
流量本身的自然增长或减少,有相应的容量报表,如果发现在某一段时间容量本身自然上升需要扩容。
针对贴吧的运营活动,比如直播等,是通过 PM 或运营预估的量,换算成容量进行扩容。这种场景属于可预知的,还有不可预知的突发情况,比如容量突然过载,导致这种现象的也分两种情况:
一是应用程序有问题,通常解决方案是回滚。网络组件与 Cache 之间的链路抖动或与其它存储层的链路抖动。再加上重试机制,可能会导致雪崩。例如贴吧分为三层:接入层、前端和后端 Service。任何一层的抖动,如果再加上重试得话,很容易雪崩。
所以,贴吧在 nginx 层做了一个模块,监控后端请求队列,如果队列超限将会下发降级命令(在 HTTP 中塞进类似于降级的标志),后面的 RPC 框架感知后会自动降级;并且修改重试策略,比如动态修改超时时间等。是否核心服务是一开始就定义好的,如果后端撑不住会进行自动降级,通过降级来保证线上服务稳定。当然,如果线上超流量,会自动抛弃。
总结一下,如果问题出在应用自身的性能上,扩个 2 - 3 倍的机器都是解决不了问题的;当时做过一个容灾的 Topic,里面涵盖了流量丢弃、降级等多种方案。正常情况是根据定期观察数量报表,通过查看 CPU 和内存使用情况来判断是否需要扩缩,在异常情况下主要通过丢弃流量、降级等来解决。
怎么做到自动降级?
因为贴吧所有的通讯协议都是 HTTP 的。所以降级标志放 HTTP 的 header 中,大致可以分为两个阶段:
第一步是手动定义好核心服务和非核心服务,一旦容量抗不住了,如果是因为后端 Service 的抖动导致的,将手动触发降级按钮在接入层的 Header 中设一个标识,如 core1(我们把服务分三级:core0、core1、core2 和其它,core0 表示只能看贴,core1 表示还能发贴)。
初期有一个降级开关,出现问题后 OP 在平台上点一下降级按扭,把 Header 塞进去,Header 往下传到 RPC 框架,RPC 框架判断哪些服务需要调,哪些服务不用调,这是第一阶段。
到第二阶段是自动降级和拒流量,在接入层里面增加一个模块,这个模块主要监控后端请求队列的大小,请求队列超限之后就会进行自动的降级。具体的做法是在接入层里面加了一个模块,统一控制服务级别,如果是用 core0 连,core1 的服务就不调了。
本期全部内容刊载在私董会专刊,仅对高可用架构后花园会员开放,回复 VIP 更多了解高可用架构后花园。
第 2 期私董会报名说明
时间:2016 年 7 月 23 日 星期六 14:00 — 17:00
地点:北京市 朝阳区 工体北路 8 号三里屯 SOHO
主题:微服务架构
议题:
不同行业、不同阶段互联网团队微服务的现状与发展历程;
支撑微服务的基础设施及成果;
本次私董会主要目的是了解及讨论不同的互联网团队微服务标准化程度、服务可管理性及可扩展性的成熟度这三个维度。传统微服务的自治、弹性、容器化、松耦合、高内聚之类传统理论也可以讨论,但不是本次私董会重点。
感兴趣的同学请访问以下报名页面,或点击阅读原文报名。由于场地限制,邀请对象可能主要针对微服务有丰富实践经验的团队代表。
http://www.bagevent.com/event/147494
本文编辑唐端荣,想更多了解各期私董会讨论全文内容请回复 VIP 了解高可用架构后花园,转载请注明来自高可用架构及包含以下二维码。
高可用架构
改变互联网的构建方式
长按二维码 关注「高可用架构」公众号