我的第6个京东618

经历过 才知道有多美

今年是我的第6个618,因为入职的时间比较"合适",使得我经历了每年两次完整的大促备战。那年还在北辰,618的当晚,我记忆的很清晰,接近凌晨1点左右的时候,我们聚集在楼道里面,大家举杯相庆,来祝贺刚刚平稳度过的大促。从此这样的场景在每年的这个时候都会经历一次,激动一次。每一次大促备战都是一场全兵演练,我们在这个战斗过程中,团队合作、技术实战、用户意识上都有一个立体的提升。站在每年的这一刻往前看,一路走过来的却是好些个不平凡的白天和夜晚。正如我们国家的乒乓球队在每次国际比赛中都有一个完美的结局,但过程从来不缺乏紧张、风险和刺激。

每逢大促开始前我们都要进行一段时间的备战准备工作,以保障线上系统平稳度过,那么我们都“备”什么呢?

首先确定自己的备战思路,梳理核心流程,找出薄弱点,对薄弱点进行具体优化,同时协调压测对优化结果进行验证。优化和压测会有一个反复的过程,后面我们还要实际演练,比如降级开关,防止实际情况发生的时候准备好的功能不可用。最后我们要做一轮培训,包括工具的使用、快速定位问题的方法、历来的教训总结。从心理层面上我们也要进行辅导,大促期间发生的问题都不是小问题,研发人员在这种压力下处理问题的心态会有很大波动以致动作变形,我们会在这方面做一次心理疏解。我们可以利用几个规则来协助我们的备战工作,比如二八法则,找出20%重要核心的功能,在找薄弱点的时候我们可以试试墨菲定律的几点规则——可能出错的事总会出错,如果你担心某种情况发生,那么它就有可能发生。最后我们还会一起列出心中最不可能出现问题的系统和功能点,重点对待列出来的问题。下图是一个备战流程的示例图。

我们常用的备战技术肯定不是重启、回滚、加机器。这里面笔者总结有分离技术、缓存技术、SQL优化、快速失败、降级限流和临近管控。

分离技术

“话说天下大势,分久必合,合久必分”,但在软件架构领域,从最早的集群部署到分布式部署再到微服务架构,一直是一个分的趋势。比如一个开放平台提供了ISV的服务、自有客户端的服务、其他平台的服务,同时还有监控服务、日志服务、消息服务等,需要将业务和服务隔离部署,线下分析和线上运行隔离。同时还可以采取线程池隔离,比如在RPC框架中的服务端为每个不同重要程度的服务各自分配一个线程池的方式。数据库层面上实现主从分离,大多数平台的业务都是读多写少,可以充分利用分库的资源。还可以再将数据库细分,按照主要业务拆分不同的数据库,结合RPC,降低数据库层面的耦合程度。

缓存技术

如果软件里面真的有一种“银弹”的话,那么我认为就是缓存,当性能优化遇到瓶颈的时候,当想抗量的时候,我们都会想到缓存。这里有一个铁律,那就是对外暴露的接口一定不能直达数据库。我们常用的缓存是Redis+JVMCache。计算Redis穿透率的时候可以通过方法调用实时监控来实现,在一个方法的总入口埋点,比如统计出1分钟调用M次请求,在请求Redis的入口埋点,统计出1分钟调用N次请求,计算命中率:N/M在使用Redis的时候要注意含有大数值的key,常常量一大则会造成Redis集群的热点访问,直接将单一节点“打死”。这样的情况下我们就要拆分大key。同时将缓存DB化,也就是不设置超时时间,全部用Redis来抗量。本地缓存常用的有Guava-cache,通过本地缓存可以做三级防护,或者做托底数据等。如果数据“尺寸较小”、 “高频的读取操作”、 “变更操作较少”,那么使用这种嵌入式缓存将非常合适。

SQL优化

每次大促前我们都要将系统中性能慢的SQL“抓”出来,而且这种工作投入产出比极高,也就是可以花费较小代价带来极大的性能收益。SQL性能问题在大多数情况下都是没有索引引起的,这可能是后续业务变化迅速,上线前代码review的遗漏,需要在这个时候统一过一遍。还有就是索引使用错误引起的,比如索引字段是字符串类型,但程序中请求DB的时候传的是Long类型,索引失效,表中数量过多,做了一次全表扫描,性能会很差。我们添加索引的时候要看区分度,计算索引区分度的方法:不重复的索引值/总记录数。值越接近1,说明区分度越高,查询的时候MySQL就会过滤掉更多的行数据。还有,添加索引最好结合MySQL执行计划来进行判断。有时候做了过多的join操作,比如超过3张表以上,我们就要想着去拆解这些SQL语句。在数据库层面可以把历史数据转出以减少数据量从而实现提高查询速度的目的。

快速失败

快速失败策略实际上是一种自我保护措施,比如调用第三方接口超时,如果超时时间设置过长,那么在访问量大的时候,就会导致请求线程积压。如果此时有线程隔离还好,若刚好没有,那么访问量一上来就会迅速导致CPU使用率飙高。比如网关系统的特点之一是会大量调用第三方接口服务,我们会对每个方法动态地设置超时时间,如果有接口方法报警,再结合JVM性能数据,我们会将这个接口的超时时间阈值调小。通过ZooKeeper下发到每一个服务节点上。在大促前,我们会重点检查MySQL、Redis、RPC等框架的RPC调用超时设置,确保每一次RPC调用都要有上限阈值。关于RPC调用超时,这里多说一下,有时候我们会发现调用端响应性能比如超过500ms,但服务端却是在100ms。除了检查网络延时、TCP重传的次数,还要注意一点任何一个成熟的RPC框架都不会让业务线程直接参与网络请求,RPC会提供一个消息队列,调用端直接跟消息队列打交道。此时,我们就要想到队列这块是否有问题了。

降级限流

这种技术实际上是“保命”的措施,降级一般有屛蔽降级和容错降级两种。一些非核心的功能,比如系统的公告、服务号、论坛等功能,而它们恰恰又请求MySQL、Redis等公共资源,为了减少这种竞争,我们就会对这些功能进行屛蔽降级,直接切断RPC调用,不再发起远程调用,返回空或其他异常提示,减少公共资源的访问。容错降级是一种放通,不会像屛蔽降级那样“暴力”,往往会有托底措施以保证用户有更好的体验,比如我们常用的本地缓存数据等。再说一下降级开关,当线上需要降级的时候,要能够秒级切换,可以采用统一配置中心来实现。同样,限流技术在平台中也是异常重要的一个措施,尤其是对网关的调用。可以采用令牌桶的方法,实现方式是GuavaRateLimter,简单有效,再结合统一配置中心,可以动态地调整限流阈值。不用重启服务器即可实现快速限流策略的调整。在网关里面还有一个设置,那就是并发度,这个是方法粒度的,对每一个调用第三方的接口都有一个并发度数值的设置,而且是动态设置,也是通过ZooKeeper下发到每一个服务节点上的。并发度具体是通过JDK的Semaphore实现的。

性能压测

性能压测可以很好地检验优化的结果,压测的过程中我们关注QPS的同时,还要结合服务器的CPU、I/O、内存等机器性能指标来定位性能瓶颈。最后预估系统的承载能力,提供数据支撑来申请服务器或Docker资源。压测工具研发可以自己写脚本,借助Jmeter、LoadRunner等工具实现,也可以有计划地联系性能压测组协助执行。最困难的还是产生真实的压力。

另外还有一个备战点,返璞归真,回到代码,重点检查一遍核心功能,把“坏味道”的代码查出来。比如“join”了很多张表的SQL语句,日志输出没有采用条件方式或占位符的方式,日志重复打印,try代码块放到了事务中,循环体中含有低性能的语句,锁代码块中进行RPC调用,等等。

总结历次的大促,主要是工具、知识、经验三个方面的备战。工欲善其事,必先利其器,我们要有一些个好的工具来辅助我们解决问题,比如监控CPU、网络的工具,监控方法性能的工具,等等。知识层面是我们历来的积累、我们认识的提高、使用工具时的指导。经验是我们以往的大大小小的教训的总结、前车之鉴,防止我们再次发生类似的事情。

临近管控

前几天,我们的欧指导还在内部备战例会上强调过一个事情,如果某个机房机器的网卡出现故障甚至某个机房整个网络出现故障,应该如何应对,当然第一时间是要把流量切走。那么如何第一时间发现这种网络故障呢,就是添加监控比如TCP重传次数报警。类似,如果依赖的某一个RPC接口出现访问异常,应该如何第一时间知道呢,也是添加监控比如性能和可用率监控。如果一个域名访问出现异常,应该如何第一时间知道呢,仍然是添加监控比如URL存活报警监控。那么从一个月前开始备战到现在临近大战来临,在临近的这段时间我们能做的而且最有效的管控措施就是对监控的差缺补漏。我们称之为临近管控。很多次的故障复盘告诉我们,几乎每次的故障排查阻碍都是因为监控粒度不够,这里面不仅仅只包含监控报警,还有日志的打印清晰以便帮助最快定位问题并解决。

"不谋全局者,不足谋一域",每次备战开始商家研发部都会做好顶层设计,保持步伐一致,坚持"书同文、车同轨、行同伦"。在每一次梳理系统过程中发现的问题上,我们都尝试多种不同的解法,无论是新技术还是成熟的解决方案,我们都充分验证,直至完全掌握,不放过一丝遗憾,力促平稳顶过每一次的流量冲击。记得去年JOS开放网关开始备战618的时候,我们要解决一个调用方和接口提供方性能不对等的问题,大家一起封闭在会议室,从监控工具的使用、代码底层IO通讯的原理、日志打印的性能各个角度去分析,连续奋战五天,最终攻克这一性能问题,让我们商家的响应速度提高了足足5倍。这样的场景还可以列举很多,不过在我看来,最宝贵的并不是我们最终采用某种技术或方案的决定,而是大家在一起探索,深入到问题解决过程中积累起的经验和我们磨合形成的这种大促战斗中的"齿轮咬合感"。从基础架构到系统的每一行代码的优化,我们不断地颠覆技术瓶颈,不断创新以适应不断增长的需求。此时此刻,备,全面充分;战,来比擒获!

本文部分内容摘自新书《架构修炼之道》第9章容错之道中的 "大促备战都备什么" 一节。

本文分享自微信公众号 - 程序架道(xindongbook17)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-05-30

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券