简介

        我们有一个基础服务,这个基础服务平时外部调用量并不是很大,我们有一个小集群(三台4d8g规格的ECS)。运行平稳,后面因为业务方需求我们我们做了一个功能扩展,因为业务方将基础服务当作MQ使用,因此访问量突然增大,平时我们tps:2-10个,这个新的功能支持后tps:200以上,高峰时期业务方评估在tps:2500-2800。

        这个完全超出了我们当时开发时的数据预估。因此联系测试组对基础服务处理能力进行了压测,果然我们是有瓶颈性问题的,最终的瓶颈点相信很多小伙伴已经猜到了,没错数据库(Mysql)出现瓶颈,在tps2700开始数据库cpu使用率开始接近100%,因此我们紧急做了一次功能升级:加了一中间数据曾MQ,先将业务方的请求存储到MQ,然后多个消费同时处理。并将参数投递单独剥离成独立项目单独部署(6台pod),原本基础服务集群服务器数量扩展至8台。

        大家可能第一时间想到这样你的数据库压力依旧存在啊,没错所以我们数据库规格也提升至32c64g。小伙伴依旧说,你这依旧很容易造成数据压力和触发瓶颈啊。没错目前还是会造成数据库瓶颈,但这时我们就要来说一说限流在我们升级中的作用了。

        从上面的优化改造,我们已经可以看出我们扩展了集群服务器数量以及投递接口剥离成独立应用,同时升级了数据库的规格。我们可以通过扩展机器数量来增加我们接口的吞肚能力和MQ的消费能力,但不可否认我们最终大压力依然在数据库的瓶颈上。

限流

        不论是 trigger api 还是 MQ 消费,我们都做了相关的限流,一方面考虑是我们系统当前的处理能力,一方面也考虑数据库的稳定性。保证在mysql最大吞吐量区间内稳定运行,相对于服务不可用,用户更能接受的是略微延迟的100%处理和附加的告警和重试,以及可是话的异常原因查看。因此我们的限流也从两个系统分别记录:trigger api(参数投递) 和 base server (MQ 消费)

trigger api 端限流

        trigger api 端限流我们使用了sentinel限流和谷歌限流,sentinel 是整体流量控制我们的4200tps,谷歌限流为单个800tps(6*800),被限流的数据可以认为是没有投递到MQ中,业务方需要重新投递或者自行处理。

      目的:trigger api 采用的pod部署,可以灵活的扩缩容,也就是不用考虑投递接口的处理能力和上线(上线会在MQ的存储和消费,以及MYSQL数据库上),之所以设定的tps大于业务方提供的峰值tps,是考虑给业务一定的上线空间,方便我们及时调整tps限流参数,内部应用内的谷歌限流主要防止sentinel宕机或者负载不均导致请求打到一台pod上做的灾备方案

base server 端限流

base server 上主要是谷歌限流tps:500 (8*500),也就是单台ecs消费MQ的速度是500tps,4000tps这个量级我们压测升级后的数据库cpu使用率85%可以平稳,超过5000tps,在MQ中会形成消息堆积,被限流的消息会重新投递到MQ等待重新消费

总结

        限流主要目的就是确保程序的稳定,相对于程序的不可用,我们更能接受的是略微延迟的100%高可用,因为我们业务方是可以接受略微延迟的。