架构师小组交流会:每期选一个时下最热门的技术话题进行实践经验分享。
第二期:因为大家对全链路压测的问题比较感兴趣,因此做了一番探讨。
参与嘉宾:滴滴技术负责人彭令鹏、魅族系统架构师何伟、唯品会应用架构负责人张广平、新浪微博技术专家聂永、大众点评交易平台技术负责人陈一方、七牛云首席架构师李道兵。
本文是对此次交流的整理,欢迎探讨。
第一轮:自由交流
滴滴彭令鹏:大家好,我是彭令鹏,目前在滴滴平台部负责整个专快车业务的稳定性和效率,之前在百度做了5年半的网页搜索部底层架构的工作。现在在滴滴主要在推四个项目,第一个项目是异地多活 ,第二个项目是全链路压测,为了尽快发现线上的一些容量风险,第三个是在推一个一键降级的平台,为了加快止损速度。第四个是服务治理,滴滴的业务也比较复杂,机器和服务规模也越来越大,我们在推一个整体的服务治理工作。
异地多活我们分三期,现在第一期差不多做完了。第一期主要是实现一个同城的Active /Standby。我们的数据两个机房都有,流量主要在一个机房,另一个机房只有少量流量,这少量流量主要是保证机房不会因为升级或其他原因,导致它不可用。第二期才会active-active,比如说两个机房分两半各50%的流量。第三期是支付这一块,现在不考虑双活,第三期我们会去考虑。当前第一期可以认为99%的流量跑在一个机房,1%的流量跑在另外一个机房,而且另外那个1%可能随时会切回来。
数据同步有两大块。第一大块在数据存储这一层,比如说用了MySQL的主从复制,还有在我们的缓存层次,为了保证命中率,我们也做了一些双写同步复制。第二个层次,对于部分业务系统,特别是像我们分单,它因为状态比较多,并且依赖的存储也比较多,如果在存储层做的话比较麻烦,所以我们直接在业务层做的双写。
滴滴的业务模式异地多活是比较难的,主要是要求的状态比较实时,打不到车立马就有人反馈投诉,不像购物一样。异地多活,我们一共有三大块技术,第一个是前面说的数据同步。第二个就是流量路由,前面说的99%和1%的流量的一个分配。第三大块我们在做降级,降级包括一个最小系统,如果数据同步真出了问题,我们会用端上面的一些数据来做补偿,反正整体还是很难的,因为订单状态机这一块还是比较复杂,状态比较多。
魅族何伟:我是魅族科技何伟,负责基础架构技术平台。魅族的互联网业务主要是用户数据同步,应用商店,音乐、视频等等,然后是push服务,push服务每天也有几个亿的推送。我们也在做全链路压测、容量管理,后面会准备上容器这一块,现在还是VM的。全链路压测我们现在正在做,简单讲一下,在入口时我们会去对流量打标记,就是着色,然后我们就能把流量根据这个着色把它调度到某一个指定的节点,在系统的各个层级我们都可以去做调度。我们不是像TCPCopy那样工作。我们的做法是把流量引到某个节点,去压某个节点的极限容量,然后我们就能看到我们的流量到底要多大的集群才能扛得起来。
七牛云李道兵:大家好,我是李道兵,负责七牛存储的技术架构。七牛是多数据中心,在全国有数个存储区域,每个存储区域有多个核心的存储机房,这些机房的规模都比较大,用于存储客户的数据。将数据存放于一个数据中心内的风险很大,如果数据中心断电、断网,会造成数据的不可用,如果一个数据中心发生灾难性事故,还可能会造成数据丢失,所以七牛使用了双数据中心的互备技术。我们将两个数据中心用裸光纤互联,当用户上传文件到某个数据中心时,系统异步将文件数据和相关原数据同步到与之互备的另一数据中心,这样当一个数据中心故障时,我们会根据故障的级别启用不同的应急预案,将请求切换到与之互备的数据中心。
微博聂永:我是来自新浪微博的聂永,现在负责微博客户端IM消息下推系统基础设施的维护和优化。前段时间还参与了公司的一个性能测试系统的建设,为系统性能提供完整压测支持,举一个例子,以前做过一个聊天室项目。我们对这个聊天室所有的功能接口都会一一的进行测试,并且会完整的模拟用户从上线到离线这个中间过程之中所有的全链路交互,并且设定每一个交互的执行的次数,这个要先去梳理用户在实际操作的所有行为。比如我们执行一次完整全链路压测,其中每个用户至少能持续30多分钟,压测强度还是很大的。同时,我们在做压测的时候,其实完全可以拿手机,和模拟的用户一同参与到压测情景中来,这样就可以以终端用户的角度,去切身体验我们的系统的稳定性,终端操作的流畅程度等。我们当时单机是直接的执行50万用户的压力测试,然后线上执行100万用户容量压测。
唯品会张广平:大家好,我是张广平,唯品会应用架构负责人。最近在做一个核心系统的重构。采购的一些商品,怎么去选购到我们销售环节去售卖,这时候就涉及到,怎么把我的库存导进来?怎么把我的商品导到销售环节,让用户能看得到?用户去浏览商品详情页面,怎么去做收藏?还有就包括结算购物车、订单支付、促销,我们把这些项目,作为我们的核心系统的重构的第一阶段。这些系统重构了以后,其他的外围的系统,包括采购、物流都做一些调用。
唯品会这几年发展非常快,基本上每年的量都在翻跟头,之前主要还是靠硬件去顶,以前的应用程序主要还是PHP。通过我们这次的重构,这次双11效果非常好,虽然碰到了一个购物车刷单的事件,但我们核心系统还是比较争气,顶下来了。谈一下刷单,刷单是需要综合地去防治,我们是从入口上判断一些请求,这些请求如果发现它是有风险的,我们会去做限流措施。因为我们的系统从入口的地方还没有一个整体的重构设计,所以有些流量进来,比如说流到购物车,购物车要去调用我们目前一些商品查询,包括库存价格之类的,对后台系统压力特别大。
我们当时是针对用户的请求去做一些分析,看看他的IP地址,调用我们的风控模块之类的,但是这一次没有防得住,因为量太大。我们系统相对来说比较健康的,这些进来的请求应该还是一些合理的请求,所以没有过多的限制。真要是扛不住,我们会去做系统限流、系统降级之类的。我们的OSP框架有一个比较有特色,我们对访问的服务做限流,比如量达到多少以后我们把后面的请求关闭,这样是保证我们正常的应用能运转下去,不然会导致后面的商品查询服务、库存、价格,会瘫掉。
两年半以前我来唯品会的时候,清一色的PHP,只有个别团队在用尝试Java做开发,但是PHP是主流,那时候我们面临一个PHP在扩展性方面的问题,尤其是它的框架,版本很多,用起来性能很差,基本上QPS都是在七八百左右,能上1000的都很少,基本上压到1000左右就崩掉了。我们投入了大量的一些硬件资源,但是发现问题不断。后来组建了一个基础架构团队,从基本的服务化框架、消息框架、配置中心,还有监控模块、安全一系列都做了开发,两年多以来我们现在基本上产品都有了。尤其是比较有特色的,是我们的OSP框架。这个框架主要是基于thrift,滴滴的那位同学也提到了thrift。我们OSP的框架也是一个thrift的长连接,一个RPC的框架。我们是作为应用架构在使用OSP。QPS从七八百,现在上万是非常轻松,比较简单的查询,可以到五六万级别。我们每次大促都要增加好多机器,但是这次双11是省下来了,还把老的系统淘汰了下来。虽然对周边没有重合的一些系统做了扩容,总体省下来了,没有去增加新的资源。我们这个重构还是值得的,我们的OSP框架扛到现在,这次双11没有出现一个问题。
大众点评陈一方:我是陈一方,来自大众点评。我原来是交易平台的,主要负责几个团队,优惠团队、订单团队和整个支付团队。现在负责整个点评的团购平台,这几年一直在做高并发的规模化的C端系统,B端系统也做了一些营销系统和结算系统。原来点评美团分别有个支付平台,融合以后,上海的支付也就是我负责的支付平台,会交到北京去。
新美大有一个支付,刚拿到牌照,原来是没牌照,但是我们是有支付团队的,做整个支付后端的能力建设,比如说支付通道、账户体系,还有前端统一支付的。支付后端挺复杂的,后端主要分3块,第一块就是支付资金渠道来源,资金渠道这块,比如支付宝,微信或银联或者任何支付通道,我们叫它支付资金渠道,这块是管理资金通道的。第二块是管理用户账户体系,因为支付会有一些资金的往来,所以你必须有明细账户,所以会有账户体系。第三块是面向公司类的业务聚集的,业务网关和支付网关。业务接入我们怎么支付,他只需要接入我们网关就可以了。网关提供能力有两种,有一种是API的模式在接入的,现在大部分是以那种组件,前端组件,比如 native 的话,我们就直接有收银台,你只需嵌进去就行,什么都不需要做。早期我们是Call API,因为那时候没有客服端的开发,后期的话,我们iOS逐渐成熟了,我们后面API全部都上了,用那种产品化平台化的模块来接,因为这样的话自动挂了我们切支付,或者是做支付上的营销,那时候他非常好做,产品化的一个过程。
第二轮:话题交流
主持人:关于全链路压测大家是怎么做的,数据是怎么处理的?生产的数据和测试的数据是放一起还是隔离的?
滴滴彭令鹏:魅族的全链路压测是压单个节点的极限,这与我们稍微有点不同,其实我们也有一个类似的做法,就是常态我们在调度的时候,可能会在地图那种业务上面放置一个哨兵节点,这个哨兵结点的流量会比别人高一点,以便提前去发现一些问题,这点和魅族类似,但是我们的压测不是这样的,我们的压测是真正直接打到整个集群,就是线上集群,和正常业务是一样的。我们的用户行为也尽可能和正常用户一致,只是打上了特殊的标记,但是其他处理行为是完全一致的,除了发券等那些和钱相关的。测试的是生产集群,这样做的目的是想真正去看这个生产集群的一个容量水平。这个和看单个节点的极限我觉得可能有点不一样。以前我在百度的时候,因为每个模块都很大,全系统的模块没几个,所以可以通过单模块的情况直接去推导整个系统,是不是全链路容量都是够的。但是来了滴滴以后,因为滴滴的业务,每一类小的接口都独立成了服务,这就导致它的服务特别多,整个全链路下来可能有几十个,所以不直接去压一压其实还是有很多问题是看不出来的。
大众点评陈一方:我的经验跟滴滴是一样的。我们也是压测单机的容量,在线生产环境的时候不一定是按等比例放大的,所以你压一台机子它支持1000QPS,但是你10台不一定能支持1万的QPS,确实有这个问题,因为它的链路太长,无法用。比如说一个节点是10,第二个加入集群中它不是不是线性扩大。
滴滴彭令鹏:我们这边的做法,第一我们在流量的模拟方面也是基于用户的历史数据去回放,打上特殊的标记,这个标记会从链路的最前端到最后端,全部染色上。针对标记的流量,我们的数据有几类处理:第一数据库这块我们是在一个proxy这样的中间件里面,直接把数据写到了一个影子表里面,相当于表级别隔离。第二个是缓存这块,因为缓存数据都会以司机的ID、用户的ID、订单的ID、坐标,作为key的组成部分,我们所有的测试数据对这些ID做了一个偏移,比如对于坐标,我们可能直接把这个坐标偏移到太平洋上面的一个地方,不会是真正的一个城市,这样保证我们的缓存调用者不用改,数据就可通过key直接隔离开。第三个是消息队列,我们会通过kafka订阅和消费消息,我们会改造生产者,让他们将消息写到一些虚拟的topic上去。压测完了以后,我们可能需要做数据清理,但是因为滴滴现在存储空间这一块其实并不是特别瓶颈,所以清理我们基本上不用做,当前是这样子。
主持人:同一个订单,用户打标是不是就是要侵入代码了?
滴滴彭令鹏:比如说做trace或者做追查,肯定自上而下要传很多上下文,那我们这样对应的一个压测标记,只是上下文里面的一个。那条路原来就是通了的,比如说对于http来讲,我记得好像就是直接放在那个http的那个query string 里面,直接下去的。
主持人:比如一个订单要写库,用户的ID是怎么来的?
滴滴彭令鹏:这些逻辑它是不变的,刚刚我说了,我们采了真实的用户数据以后,会对一些ID类数据做偏移,比如说用户Passenger ID和Driver ID,正常的可认为是一些手机号,但偏移时我们会把它的最高位,设置成特殊值,这是一类。另外一类是坐标,我们会把这个坐标,比如说北京直接平移到太平洋上面的一个经纬度,即平移到一个虚拟城市。我们系统会将这些ID或坐标作为key去存储数据,包括缓存的key,那对应的,这些key也被我们偏移了,所以存储的数据也就通过key隔离了。
大众点评陈一方:我分享下我们当时压测的经验,我们在压测线上服务的时候,我们先压的读,读数据的这块压测比较容易,而压测写,其实挺难的。刚才滴滴分享他们经验,每个团队不一样。我们的订单系统,当时压的时候就是很难就写入了。因为有一些问题,有很多数据写入我们一次访问,后面一个集群,下面可能挂了一堆二三十台的实例数据表。遇到这样的问题怎么办呢,我们当时是分段压测,就是先压数据层到db,就是先压db的的极限,db的极限压出来,比如说一个集群在db写的场景下支持2万,那根据这个集群服务器数量倒推,每台服务器写了多少db,然后再去测单台的服务的性能,然后再乘以集群数量,根据流量的翻量比。
主持人:我们在谈压测,很多系统有第三方服务的,比方说第三方支付,对接外部的银行,没办法要求第三方服务配合你,那这个时候你们怎么办?
大众点评陈一方:第三方有两种做法,一种做法就是,如果它不是一个强依赖的话,你就直接把它关掉,最高峰的时候肯定不够用,你就把他降级。这是第一个,第二个像支付,他强依赖的话,系统第三服务方会给你SLA,你根据它的极限值往下压就行了,如果他那个值没达到,你找他去,他达到了,你那就算了。
滴滴彭令鹏:我们是这样子的,因为有一种场景,虽然支付那边会给你承诺SLA,但我们的系统容量可能是高于它的。那这个时候怎么压呢?我们本身的压测是分为两期的。第一期,是在分单以前的压测,第二个是整个全链路。分单以前压测,是当流量到了分单系统以后,直接把它截断,从而保证这样的一些流量,不会走到下游去,对于支付也是一样的,你可以在支付模块的上游那里做一个截断。
主持人:做高可用有一个指标,就是要达到五个九。但最后在落地时,在多一些场景上面这些指示有实际测量吗,后面有没有一个定论去达到这个要求,或者没有达到这个要求?
滴滴彭令鹏:滴滴现在这边,当前是三个9多一点点。我们未来2017年的一个目标也就是三个9一个五。做到四个9很难,对消息交易系统来说。落实这一块第一是我们有一个专门的第三方组织,来整体评比各个部门的稳定性指标,做得还是比较严的。第二个是老大,包括CTO对这一块特别重视,基本上今年每个团队有30%的kpi是稳定性。
大众点评陈一方:我们跟滴滴挺像的,我们也是第三方的,比如运维部部或者质量部,他会给你出报表,因为它的报表是一周或者一个月的,我们现在交易系统,要求四个9,但是我们其实达到三个9多一点。高层管理会看这个指标,中层也会看这个指标,然后这样叠在每个基层,他也会看这个指标,所以这样已经形成一个机制了。