一个真实的问题场景:某接口服务,对外部服务提供回调接口,调用量、调用频率分布并不平均,在某些时刻(大量运营活动投放)后,可能短时间会有大量调用,达到峰值,而其他时间的调用频率很低,可能只有峰值的1/3甚至1/5的量级。另外,调用高峰的时间并不能准确预估,需要结合监控得知调用增长情况。
相信有过C端后端开发经验的朋友们都会了解这类问题,这应该也是非常常见的情况。一些典型的场景:春节红包、营销大促、双十一/618等等,都会面临极度流量高峰。还记得17年所在某家公司的春节红包活动,参与了整个项目从12月初开始倒排一直到最终上线完成红包活动的全过程,尤其春节当天晚间的四个小时,一直抱着电脑关注流量情况和统计、报警邮件。尽管当时只是作为一个模块的开发,但对整体也有一定的了解,并收益匪浅。
在这类活动中,除了业务本身的复杂性,作为开发最为关心的就是如何实现。而有过相关经历,或曾经深入研究过这类场景的各位应该都清楚,压力与资源,可能是面临的最大问题。
先回顾17年春节红包活动当时的整个过程:
1、各方沟通、明确需求
2、敲定各部门所负责的流程,对接的功能接口,整体性能指标和拆解后的性能要求,分别启动开发
3、基于上述条件,确定方案细节,实现、整体联调、测试(功能+压力+故障)。
4、项目整体上线,活动期间各方关注数据,随时跟进解决问题。
整个流程虽长,但各方拆解之后责任链依然清晰,所以在制定方案细节时,只需要考虑内部的实现,对外提供的能力、性能指标。接下来,最大的问题就是如何保障在巨大的峰值压力下,保证服务的稳定性,和达到预期的性能指标?
压力要求:10万qps下,接口整体响应耗时不超过100ms。根据内部的经验,服务部署采用实例机器(虚拟机),普通实例节点,按照单服务实例可承受qps 5k计算,那么也需要200个服务实例(虚拟机)。考虑到除了应用服务器,还有db(分库分表)、缓存(redis)、负载均衡、服务中心等其他相关设施的设备要求,而数据库和缓存往往需要物理机部署,总的资源需求必然会是一个很大的数字。而这,只是其中已经偏流程后期的某个环节的资源需求。而19年的春晚红包活动,活动的资金和资源投入都远远大于17年的这次,所需的资源和整体活动的实现难度也可想而知了。
关于资源,这里以服务器资源为例,在计算所需的数量、规则之后,提预算,内部转移或进行新的采购,这个周期通常不会太短。毕竟短时间调度这么大的资源并不容易。而且考虑使用周期,如果没有比较清晰的后续规划,那么也必然造成大量的资源浪费。
另一种方案就是采购云资源,只在活动期间采购使用,结束后释放即可。由于云资源是按照使用时长和数量计费(通常会抽象成计费单位),所以不会造成资源浪费。但这也可能遇到问题,云服务也并非足够稳定,而且由于采购云服务相当于资源和运维外包,出现问题往往需要提工单解决,即使加急,服务商出于各种优先级和内部突发事件等级的考虑也未必能立即快速支持。即使有后续的解决和赔偿措施,在很多情况下也是得不偿失的。
之前使用过某家云服务商的服务(top 5),其虚机在18年因漏洞紧急升级,造成部分数据损失,但最终的赔付仅是按照停机市场为基础进行赔付。所以就会有多云方案的产生,避免对一家云服务商过于依赖,导致业务受制。
近几年,随着容器技术的发展,弹性计算、serverless也应运而生,提供了一种新的思路和方案。资源的动态扩容和云上弹性计算能力(例如阿里云的函数计算)的提供,让资源需求方有了更好且更方便、更经济的选择。
旧的资源采购模式,即使在资源到位之后,各种基础软件安装、服务部署调试都是很大的工作量,尽管会使用脚本来进行批量部署。在docker、k8s的持续发展下,这一过程的工作量和耗时得以大大缩减,极大地提高了效率,应对流量高峰低谷时的动态扩容缩容动作也可以更从容。
本文是服务&容器系列的开篇,以需要解决的核心问题作为铺垫。在后续篇章中,将逐步开始对相关技术进行深入研究,并解决典型的问题作为实践,从中发现使用中可能遇到的问题并解决,深入掌握。