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

集群如何控制 QPS?

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

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

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

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

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

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

    感谢

    17 条回复    2024-11-19 12:35:07 +08:00
    vus520
        1
    vus520  
       49 天前
    在外面套一个网关,在网关上设置限制,更简单。
    securityCoding
        2
    securityCoding  
       49 天前
    redis 写个 lua 限流脚本就好了,不要用太复杂的分布式限流方案
    cookii
        3
    cookii  
       49 天前 via Android
    1. 套网关,网关通常有现成的实现
    2. 用 redis
    chenfang
        4
    chenfang  
    OP
       49 天前
    @securityCoding 目前能想到 直接可以用的 就是这个了, 有试过性能如何么? 我们流量一天 60 亿, 当然也不是所有的都会去走限流
    chenfang
        5
    chenfang  
    OP
       49 天前
    @cookii 网关我理解的是限制进来的请求, 再到里边的话 也可以用么?
    cookii
        6
    cookii  
       49 天前 via Android
    @chenfang 外层限制了,里层就不用管了呗
    jov1
        7
    jov1  
       49 天前
    假设这样一个场景,你的某个业务需要调用一个第三方接口,但是第三方接口有 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  
       49 天前
    @chenfang #4 我这边基本用的腾讯云 redis,会有十几 ms 的耗时,有热点就扩分片完事
    ymy3232
        9
    ymy3232  
       49 天前
    目前用的 Sentinel ,集群里 400+服务,服务器 CPU 负载不高没怎么关注 Sentinel 的影响,整体来看应该没啥影响,用它的目的是为了避免服务重启的时候直接被打爆起不来,目前来看效果一般,可能是没理解它的 warm-up 机制或者流量在到 Sentinel 之前就扛不住了。redis 、网关这些都考虑过,对于我们来说成本太大,Sentinel 几乎 0 成本
    xuanbg
        10
    xuanbg  
       48 天前
    搞个网关,网关上实现限流,用令牌桶
    chenfang
        11
    chenfang  
    OP
       48 天前
    @ymy3232 sentinel 用的是单机的方式么?
    huangzhiyia
        12
    huangzhiyia  
       48 天前 via iPhone
    自己反代 API 啊 想怎么限流怎么限流 还能看情况定制缓存策略
    Yukineko
        13
    Yukineko  
       48 天前
    Sentinel 还行,在阿里那堆东西里面属于还算比较好用的
    sujin190
        14
    sujin190  
       48 天前
    那分享下之前做的项目吧: https://github.com/snower/jaslock-spring
    有令牌限流 TokenBucketFlow 实现,性能肯定够用,我们自己项目也再用

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

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

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

    同时每个独立的加 1 操作和其包含的过期时间都是独立同步到从节点的,客户端连接从节点命令会自动发送到主节点,所以客户端这边是整个集群的所有节点都是一样的,多核支持性能不够问题可以通过扩容 cpu 核心数和内存就行,不过因为指令简单,支持的 qps 很高,一般应该不需要考虑性能不够问题
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3433 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 04:57 · PVG 12:57 · LAX 20:57 · JFK 23:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.