用户的每个请求都会分配一个优先级,并且在微服务的链式调用下,下游请求的优先级也是继承的,比如我请求登录,那么检查账号密码等一系列的的后续请求都是继承登录优先级的,这就保证了优先级的一致性 。
每个后台服务维护了业务优先级的 hash 表,微信的业务太多了,不是每个业务都记录在表里,不在表里的业务就是最低优先级 。

文章插图
2. 用户优先级很明显,只基于业务优先级的控制是不够的,首先不可能因为负载高,丢弃或允许通过一整个业务的请求,因为每个业务的请求量很大,那一定会造成负载的大幅波动,另外如果在业务中随机丢弃请求,在过载情况下还是会导致整体成功率很低 。
为了解决这个问题,可以引入用户优先级,首先用户优先级也不应该相同,对于普通人来说通过 hash 用户唯一 ID,计算用户优先级,为了防止出现总是打豆豆的现象,hash 函数每小时更换,跟业务优先级一样,单个用户的访问链条上的优先级总是一致的 。
这里有个疑问,为啥不采用会话 ID 计算优先级呢,从理论上来说采用会话 ID 和用户 ID 效果是一样的,但是采用会话 ID 在用户重新登录时刷新,这个时候可能用户的优先级可能变了,在过载的情况下,他可能因为提高了优先级就恢复了,这样用户会养成坏习惯,在服务有问题时就会重新登录,这样无疑进一步加剧了服务的过载情况 。
因为引入了用户优先级,那就和业务优先级组成了一个二维控制平面,根据负载情况,决定这台服务器的准入优先级(B,U),当过来的请求业务优先级大于 B,或者业务优先级等于 B,但用户优先级高于 U 时,则通过,否则决绝 。

文章插图
3.自适应优先级调整在大规模微服务场景下,服务器的负载是变化非常频繁的,所以服务器的准入优先级是需要动态变化的,微信分了几十个业务优先级,每个业务优先级下有 128 个用户优先级,所以总的优先级是几千个 。
如何根据负载情况调整优先级呢?最简单的方式是从右到左遍历,每调整一次判断下负载情况,这个时间复杂度是 O(n), 就算使用二分法,时间复杂度也为 O(logn),在数千个优先级下,可能需要数十次调整才能确定一个合适的优先级,每次调整好再统计优先级,可能几十秒都过去了,这个方法无疑是非常低效的 。
微信提出了一种基于直方图统计的方法快速调整准入优先级,服务器上维护者目前准入优先级下,过去一个周期的(1s 或 2000 次请求)每个优先级的请求量,当过载时,通过消减下一个周期的请求量来减轻负载,假设上一个周期所有优先级的通过的请求总和是 N,下一个周期的请求量要减少 N*a,怎么去减少呢,每提升一个优先级就减少一定的请求量,一直提升到 减少的数目大于目标量,恢复负载使用相反的方法,只不是系数为 b,比 a 小,也是为了快降慢升 。根据经验值 a 为 5%,b 为 1% 。

文章插图
为了进一步减轻过载机器的压力,能不能在下游过载的情况下不把请求发到下游呢?否则下游还是要接受请求,解包,丢弃请求,白白的浪费带宽,也加重了下游的负载 。
为了实现这个能力,在每次请求下游服务时,下游把当前服务的准入优先级返回给上游,上游维护下游服务的准入优先级,如果发现请求优先级达不到下游服务的准入门槛,直接丢弃,而不再请求下游,进一步减轻下游的压力 。
六、总结微信整个负载控制的流程如图所示:

文章插图
- 当用户从微信发起请求,请求被路由到接入层服务,分配统一的业务和用户优先级,所有到下游的字请求都继承相同的优先级 。
- 根据业务逻辑调用 1 个或多个下游服务,当服务收到请求,首先根据自身服务准入优先级判断请求是接受还是丢弃 。服务本身根据负载情况周期性的调整准入优先级 。
- 当服务需要再向下游发起请求时,判断本地记录的下游服务准入优先级,如果小于则丢弃,如果没有记录或优先级大于记录则向下游发起请求 。
- 下游服务返回上游服务需要的信息,并且在信息中携带自身准入优先级 。
推荐阅读
- 有着沉鱼落雁之容,闭月羞花之貌?有着36亿年历史的细菌是整个生命史中的耐力冠军_1
- 河南|河南老人钓到一“乌龟”,壳上插4箭,专家:一竿钓了18亿
- 李嘉诚取10亿现金?李嘉诚现金流的重要性
- 抖音粉丝超过一亿的用户?抖音粉丝过万的有多少人
- 侏罗纪世界|2022暑期档院线总票房破8亿:《侏罗纪世界3》独揽“半壁江山”
- 苹果|因反派神似苹果CEO库克引热议!《侏罗纪世界3》内地票房破4亿
- 华为|华为智能穿戴全球累计发货量破亿:运动健康军团三大新研究启动
- 银河系|迄今最详尽银河系星系图发布:含20亿颗恒星 美极了
- 苹果|美股大跌 标普500进入熊市:苹果特斯拉一夜蒸发千亿元 中概股暴跌
- 苹果|罗永浩债务还剩不到1亿:直言想在AR平台上做类似苹果一样公司
