集群如何控制 QPS? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
chenfang
V2EX    程序员

集群如何控制 QPS?

  •  
  •   chenfang 344 天前 2298 次点击
    这是一个创建于 344 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如目前有一个 tomcat 集群,我想控制所有 tomcat 请求一个 url 的频次是 10QPS

    我有想过 Sentinel,但是有点顾虑 一个是这个是阿里的东西 用过阿里的东西应该都有体会

    再有就是我搜了搜只有单机使用的方法,具体集群如何实现官方并没有给出可以用的代码,需要自己去实现高可用,只是说了一下方法

    有人用过 Sentinel 控制集群 QPS 么? 如何实现的? 性能如何?

    或者其他的比较成熟的方案也可以

    感谢

    17 条回复    2024-11-19 12:35:07 +08:00
    vus520
        1
    vus520  
       344 天前
    在外面套一个网关,在网关上设置限制,更简单。
    securityCoding
        2
    securityCoding  
       344 天前
    redis 写个 lua 限流脚本就好了,不要用太复杂的分布式限流方案
    cookii
        3
    cookii  
       344 天前 via Android
    1. 套网关,网关通常有现成的实现
    2. 用 redis
    chenfang
        4
    chenfang  
    OP
       344 天前
    @securityCoding 目前能想到 直接可以用的 就是这个了, 有试过性能如何么? 我们流量一天 60 亿, 当然也不是所有的都会去走限流
    chenfang
        5
    chenfang  
    OP
       344 天前
    @cookii 网关我理解的是限制进来的请求, 再到里边的话 也可以用么?
    cookii
        6
    cookii  
       344 天前 via Android
    @chenfang 外层限制了,里层就不用管了呗
    jov1
        7
    jov1  
       344 天前
    假设这样一个场景,你的某个业务需要调用一个第三方接口,但是第三方接口有 QPS 限制,比如 20/每秒,
    但是你的服务是集群部署的,通过 guava 的令牌桶可以实现单机的 QPS 控制,比如 RateLimiter.create(20, 1, TimeUnit.SECONDS);
    如果部署 3 个集群,那么 QPS 最大可能为 60/每秒,这样就超过三方接口限制。
    那么这种情况可以拆分为如何将 20 合理的分配到 3 个集群上,简单点使用 xxl-job ,根据分片总数和当前分片序号,以及你需要限制的 QPS ,计算得到每个分片的大小,替换到令牌桶上就可以了。

    下面这个分配总数 count 就是你程序里面要定义的 qps 了。
    RateLimiter.create(count, 1, TimeUnit.SECONDS);

    ```
    public static void main(String[] args) {
    // xxl-jpb 返回集群分片信息
    ShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo();


    int totalSize = 20; //集群自己配置总的 qps
    int shardingTotal = shardingVO.getTotal(); // xxl-job 返回的当前分片总数
    int shardingIndex = shardingVO.getIndex(); // xxl-job 返回的当前分片序号

    int count = getShardingCount(totalSize, shardingIndex, shardingTotal);
    System.out.println("分片 " + shardingIndex + " 分配数量: " + count);
    }

    public static int getShardingCount(int totalSize, int shardingIndex, int shardingTotal) {
    int baseSize = totalSize / shardingTotal; // 每个分片的基本数量
    int remainder = totalSize % shardingTotal; // 余数部分

    // 前 remainder 个分片分配 baseSize + 1 个元素,之后的分片分配 baseSize 个元素
    return shardingIndex < remainder ? baseSize + 1 : baseSize;
    }
    ```
    securityCoding
        8
    securityCoding  
       344 天前
    @chenfang #4 我这边基本用的腾讯云 redis,会有十几 ms 的耗时,有热点就扩分片完事
    ymy3232
        9
    ymy3232  
       344 天前
    目前用的 Sentinel ,集群里 400+服务,服务器 CPU 负载不高没怎么关注 Sentinel 的影响,整体来看应该没啥影响,用它的目的是为了避免服务重启的时候直接被打爆起不来,目前来看效果一般,可能是没理解它的 warm-up 机制或者流量在到 Sentinel 之前就扛不住了。redis 、网关这些都考虑过,对于我们来说成本太大,Sentinel 几乎 0 成本
    xuanbg
        10
    xuanbg  
       344 天前
    搞个网关,网关上实现限流,用令牌桶
    chenfang
        11
    chenfang  
    OP
       344 天前
    @ymy3232 sentinel 用的是单机的方式么?
    huangzhiyia
        12
    huangzhiyia  
       344 天前 via iPhone
    自己反代 API 啊 想怎么限流怎么限流 还能看情况定制缓存策略
    Yukineko
        13
    Yukineko  
       344 天前
    Sentinel 还行,在阿里那堆东西里面属于还算比较好用的
    sujin190
        14
    sujin190  
       344 天前
    那分享下之前做的项目吧: https://github.com/snower/jaslock-spring
    有令牌限流 TokenBucketFlow 实现,性能肯定够用,我们自己项目也再用

    非 spring 的原始 java driver: https://github.com/snower/jaslock

    需要用服务端: https://github.com/snower/slock 也支持高可用部署,支持多核,性能不够加内存加机器 cpu 核心就好了
    chutianyao
        15
    chutianyao  
       344 天前
    分布式限流么, 一线厂家几乎都有自己的一套. 基本原理就是集群设定一个总的限流阈值,比如 1w qps, 然后根据当前的 pod 数量,计算每个 pod 的单机限流阈值. 比如 100 个 pod,那就是每个 pod 单机限流 100,然后下发给各 pod 就是了

    至于单机限流,无非就那么几种,滑动窗口、令牌桶、漏桶之类的,或者要求不高的直接用 guava 里的 ratelimiter
    nc2017
        16
    nc2017  
       331 天前
    @sujin190 这本质还是用了 redis 做集中令牌存储?
    sujin190
        17
    sujin190  
       331 天前
    @nc2017 #16 并不是,独立服务并没有用到 redis ,虽然本至还是内存存储的原子计数器,区别就是这个服务对每个 key 的加 1 操作都有独立的超时时间,而且是主动精确超时时间,不像 redis 非精确超时时间,超时后自动减 1 ,并且每个 key 可以设置可以加到的最大值,到这个值之后会 wait ,而这个等待时间也是可以设置的,通过这三个参数就可以设计出不同的限流器,TokenBucketFlow 只是某个特定参数组合的客户端封装实现,服务器这个都只有一个操作,因此性能非常可以,内存使用量也不算特别大

    同时每个独立的加 1 操作和其包含的过期时间都是独立同步到从节点的,客户端连接从节点命令会自动发送到主节点,所以客户端这边是整个集群的所有节点都是一样的,多核支持性能不够问题可以通过扩容 cpu 核心数和内存就行,不过因为指令简单,支持的 qps 很高,一般应该不需要考虑性能不够问题
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     909 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 21:48 PVG 05:48 LAX 14:48 JFK 17:48
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86