服务器限流方案设计

本周在做运营平台的限流方案设计,整理如下。

概要

目前运营平台并无限流功能。带来的结果是:

  1. 有爆款活动上线时,需要提现扩容,防止服务被高并发流量给打挂掉;
  2. 不同业务活动会相互干扰,特别是当有些活动被恶意攻击的情况下;

我们希望在极端情况下,运营平台的业务功能仍能得到部分保障。

这里有一个问题是为何限流不放在网关层做,毕竟想nginx这样成熟的服务是自带有限流功能的。1是nginx的限流方案相对简单,主要是对uri地址的限流,而我们的需求是需要通过解析header或者body来获取到caller id和对应的act id;2是因为我们的服务存在多个网关,一个是对端上请求的,一个是对小程序请求的,还有一个是对内部服务的; 3是nginx动态配置调整也不方便。

业务现状

  1. 目前运营活动的请求通常来之三端,分别是NA(ios、android),独立小程序和主小程序;
  2. 运营平台同时提供了部分基础功能(如赶车闹钟设置),供公司内部其它服务使用;
  3. 不同的活动通过activity id进行区分;
  4. 同一个activity id通常会调用不同的方法(method name);

限流配置

{
	node_num = 10, -- 服务器节点个数
    act_limit = { -- 运营活动限流
        { -- 不同的活动id
            actid = "bus_hblb_20210510",
            switch = true, -- 开关
            act_quota = 100, -- 总的配额,单位为秒
            terminal_detail = {
                na = { -- NA端
                    terminal_quota = 30,
                    method_detail = {
                        method_name_list = {"method1", "method2"},
                        method_quota = 20,  -- method_name_list共用该配额
                    },
                },
                main_applet = { -- 主小程序
                    terminal_quota = 30,
                    method_detail = {
                        method_name_list = {"method1", "method2"},
                        method_quota = 20,
                    },
                },
                independent_applet = { -- 独立小程序
                    terminal_quota = 40,
                    method_detail = {
                        method_name_list = {"method1", "method2"},
                        method_quota = 20,
                    },
                },
            },
        },
    },
    service_limit = { -- 内部服务接入限流
        {
            caller_id = "taxi", -- 调用方
            switch = true,
            quota = 100,
            method_detail = {
                method_name_list = {"method1", "method2"},
                method_quota = 20,
            },
        },
    },
}

技术选型

考虑使用golang标准库中就自带了限流算法的实现,即golang.org/x/time/rate。 该限流器是基于Token Bucket(令牌桶)实现的。

简单来说,令牌桶就是想象有一个固定大小的桶,系统会以恒定速率向桶中放Token,桶满则暂时不放。 而用户则从桶中取Token,如果有剩余Token就可以一直取。如果没有剩余Token,则需要等到系统中被放置了Token才行。

配置变更

支持限流配置的动态变更,考虑到限流实现和历史访问相关,需要注意代码实现丢掉历史信息。

统计信息

需要将线上配置的限流参数暴露出来,供业务侧根据活动的优先级调整不同活动的限流配额。

上线部署

对于已经在线上的服务,可以通过历史经验填写限流参数,如果不填写则不做限流;

对于新上线的服务,原则上都需要添加限流信息(作为上线前checklist中的一项)。考虑到新上线活动流量的不确定性,刚上线时可以把限流开关关掉,等活动运行一段时间积累一定数据后再重新打开。

补充说明

1、为何不选用集群限流方案?

答:目前的方案基于单机限流,在每台服务器配置相同且负载均衡做好的情况下,基本能做到和集群限流的参数接近。目前这两个前提基本能满足。如果采用集群整体限流方案,需要添加中心节点,系统复杂度大幅上升。

2、在复杂环境下如何设计限流方案?

答:我们当前使用docker环境,且docker分配的资源配额一致,所以限流方案比较简单。如果存在多个服务部署在同一台物理机的场景,我们就需要考虑到不同服务之间的干扰,毕竟限流的目的就是保护自己不被流量打垮。在这种场景下限流的阈值也会随着服务器负载的变化而变动,限流阈值自适应服务运行场景。

参考文献

Golang限流器time/rate使用介绍 - 知乎

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值