电商类的网站不可避免要面对大促的话题,每次大促对系统的可用性要求很高,是对技术人的一次考验,所以要做好整套的方案来保证。
我所在的公司为手机公司,每年新品销售的时候,流量也是非常大,是平时的10倍,甚至上百倍,今天来聊一聊稳定性相关的话题,谈下如何做好稳定性。
一、梳理主链路,保证主链路的可用性
电商类的主链路就是从商品浏览,到添加购物车,保存订单,支付等完整下单链路。梳理主链中的目的有:
1、避免单点
一般来说要尽量避免在主链路中访问数据库,因为数据库扩容比较麻烦,当然如果公司的分库分表做的很好了,也是可以的,主要是保证每一个节点都可以水平扩容。
2、梳理强弱依赖
什么是强、弱依赖,这个网上已经有不少介绍了,即如果调用某个服务挂了不影响主流程,或者可以通过其它手段恢复,则不要返回错误给用户,或者可以通过开关降级掉。
举个例子:添加用户地址时,需要发MQ记录操作流水,其中MQ如果发送失败应该只打印下日志,而不应该直接返回错误给用户。
3、避免不合理的调用
常见问题有:
循环调用服务;
调用接口过多(见到一个页面下来就调用4,5个接口的)
常见的方案有:
1)、缓存
一些访问量特别大的,对数据一致性要求没那么高的,可以通过缓存来降低压力。
像商品详情页的获取商品详情接口,我们一般将接口缓存一段时间的。
2)、静态化
一些数据如果可以通过静态化的,尽量不要通过接口。
如添加地址时每一个省下面有多少市,市下面有多少区,这些地址信息就不要调用接口了,完全可以放入到js中,然后放上CDN,就可以大大降低系统交互了。
3)接口合并
将一些小的接口做聚合,尽量减少和后端的交互。
二、快速失败、防止雪崩
1、超时参数
连接各种中间件参数,如Mysql、Redis、RabbitMQ等,保证中间件出问题不要出现雪崩;
还要调用其他服务的,大部分公司会采用微服务,服务之间调用需要保证超时时间,现在最新的方案是逐层动态计算,即一个接口要串联调用5个服务,总的超时时间设置为5秒,在调用第一个服务后还剩下4.8秒,则在调用第2个服务的时候会把4.8作为超时时间传下去,有兴趣的大家可以网上搜索下。
2、限流
主要方案分几层:
接入层:可以在接入层中间件上,如nginx做限流,笔者公司自己开发过nginx插件,可以针对每个URL进行保护;
服务层面,注意线程池等相关参数的设置,可以用Hystrix进行保护。
三、削峰
一些关键场景同时访问量特别大,就需要采用削峰了,像添加购物车型、保存订单按钮,常用做法有:
1、验证码
2、排队
3、随机延迟
即点按钮后,随机延迟1-3秒才提交请求
这个可以根据自己的业务情况去选择。
四、做好Checklist
每次大促需要做好多准备工作,很多细节,一般前面已经加班好久了,真正到大促那天好多人已经非常疲惫了,为了保证发布的有序,需要把所有线上操作全部合成一个大的Checklist,保证现场发布有序进行。
五、做好故障预案
出了问题之后,如果还要去想做哪些事情,可想而知故障处理的时效是无法保证的,所以要提前做故障预案做好,做到快速止损。
评价一个故障预案是否好有几个标准:
1、是否可执行
即每一项做的事情一定是具体的步骤,如执行什么shell命令,还是在某个后台操作什么东西
2、责任到人
3、要覆盖所有核心场景
一般分2种:可预知的和不可预知的,对于可预知的,故障范围已知的,事先明确操作步骤,像一些中间件没做高可用,还需要现场做一些操作的,请提前写明做哪些事情;
针对只知道现象,不知道什么原因的,也要明确标准操作流程,如先降级,再限流等
还有一些通用的其它方案:如容量评估、监控等就不在这里细说了。
最后说下最佳实践:
一、现场所有人坐在一起
开发、运维现场一定要坐到一起,有条件的可以专门坐到一个密封的办公室里,这样出了问题之后大家可以快速沟通,执行Checklist也非常高效。
二、保证现场有序
一定要有一个人坐镇全局,出问题的时候要不要采取措施,都由这个人来做统一指挥,这样可以保证现场的秩序是可控的。
如果一出问题全跑到运维那里,那个时间运维的压力特别大,很容易出错。
三、提前操作完毕
即所有Checklist的东西至少一定要在大促开始前1小时全部做完,因为如果临到活动开始前还在不停的操作,一定会手忙脚乱,很容易出问题。
这就需要架构上、方案上要做好,保证所有东西一定能提前发布,这里很多细节,像需要发布的页面提前发布上去做好灰度,准点开放自动解除灰度。