V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
liaojl
V2EX  ›  Java

请教, Java 怎么控制 API 调用的频率

  •  
  •   liaojl · May 29, 2019 via Android · 9766 views
    This topic created in 2529 days ago, the information mentioned may be changed or developed.
    服务端需要调用第三方 API,但是第三方 API 有调用频率限制,多次超出调用频率会被拉黑。目前用线程池来调 API,怎么才能控制服务器端每分钟调用次数不超过指定数量,比如每分钟不超过 500 次。
    36 replies    2019-05-30 19:52:38 +08:00
    micean
        1
    micean  
       May 29, 2019   ❤️ 2
    guava 有 ratelimiter
    itechify
        2
    itechify  
    PRO
       May 29, 2019 via Android
    用变量来记录当前时间分钟对应的调用次数可以否?到下一分钟,重置为 0,这分钟内每次调用增加 1,到 500 提示失败
    itechify
        3
    itechify  
    PRO
       May 29, 2019 via Android
    我渣渣哈哈~没做过这个东西,胡乱猜想的
    liaojl
        4
    liaojl  
    OP
       May 29, 2019 via Android
    @micean 好东西,正是我想要的
    liaojl
        5
    liaojl  
    OP
       May 29, 2019 via Android
    @oneisall8955 我也这么想过,但是后来一想,如果负责置 0 的那个线程阻塞或者发生什么意外,那就 gg 了
    runtu2019
        6
    runtu2019  
       May 29, 2019
    @liaojl 同时放个时间戳,变量只做自增作用,同时校验时间戳和数量,单个线程崩了应该没事
    liaojl
        7
    liaojl  
    OP
       May 29, 2019 via Android
    @runtu2019 好办法
    securityCoding
        9
    securityCoding  
       May 29, 2019
    1. guava 单机限流
    2.阿里开源的 Sentine
    l8g
        10
    l8g  
       May 29, 2019
    单机可以看下 Guava 的 RateLimiter
    分布式场景下用 Redis 的 zset 做个简单的限流也可以
    palmers
        11
    palmers  
       May 29, 2019
    liaojl
        12
    liaojl  
    OP
       May 29, 2019
    @securityCoding
    @l8g
    @palmers
    谢谢各位!
    dawncold
        13
    dawncold  
       May 29, 2019
    一个好的 API 设计会告诉你当前时间窗口还剩多少次调用,遵照执行就好
    gz911122
        14
    gz911122  
       May 29, 2019
    rxjava 被压
    CoderGeek
        15
    CoderGeek  
       May 30, 2019
    简单的限流就可以实现 楼上都说了
    xuanbg
        16
    xuanbg  
       May 30, 2019
    redis 里面搞一个过期时间为 1 分钟的 key 作为计数器,读到计数器到达 500 了,就报调用失败或者扔到队列里面去等下一分钟再调用。队列可以满足削峰的需求,但不能满足你每分钟平均次数超过 500 的需求。如果平均每分钟超过 500 的话,只能报错了。
    jorneyr
        17
    jorneyr  
       May 30, 2019
    lihongjie0209
        18
    lihongjie0209  
       May 30, 2019
    老老实实写日志到 redis 或者是数据库中, 调用之前先查询一下日志.

    基于 guava 这种内存型的, 服务器重启就 GG 了.
    aino
        19
    aino  
       May 30, 2019
    俺用的 RateLimiter
    luozic
        20
    luozic  
       May 30, 2019 via iPhone
    kong/其他平台的网关
    liaojl
        21
    liaojl  
    OP
       May 30, 2019 via Android
    @jorneyr 是限制我方调用第三方 API 的频率,不是限制客户端调我方 API 的频率😂,不过还是感谢哈,Nginx 还可以这么用
    liaojl
        22
    liaojl  
    OP
       May 30, 2019 via Android
    @lihongjie0209 哈哈,只是限制每分钟的调用频率,不限制历史总的调用次数的
    lzxz1234
        23
    lzxz1234  
       May 30, 2019
    选定一个时间单位,记录这个时间段内所有请求发出去的时间,每次请求时查看最早的那个请求时间,大于时间单位通过并更新请求时间,否则等待或者返回 false,一个循环数组就可以搞定了,根据目标频率选一个合适的大小就可以
    clarkyi
        24
    clarkyi  
       May 30, 2019
    guava 这种不支持分布式吧?多台设备就 gg 了,redis+guava 考虑一下
    lihongjie0209
        25
    lihongjie0209  
       May 30, 2019
    @liaojl
    00:00:03 秒调用了 300 次
    00:00:05 服务器重启
    00:00:40 重启成功
    00:00:59 又调用了 300 次

    总数超了
    cyhulk
        26
    cyhulk  
       May 30, 2019
    @lihongjie0209 要看场景的,如果是考虑性能问题限制次数,重启了,重新 300 也无所谓,反正服务器重启过了,300 也压的住,直接内存,相对于 redis 调用的性能损耗,要划算的多
    luozic
        27
    luozic  
       May 30, 2019 via iPhone
    网关也能干出去调用的,代理一下就行。
    temp178
        28
    temp178  
       May 30, 2019 via Android
    单机的话简单的限流算法就可以 令牌桶算法之类的
    vtoee
        29
    vtoee  
       May 30, 2019
    有点类似于调百度地图 API 坐标转换
    lihongjie0209
        30
    lihongjie0209  
       May 30, 2019
    @cyhulk 这个限制是第三方 API 的, 不是楼主的
    EastLord
        31
    EastLord  
       May 30, 2019
    目测 阿里的 Sentine 满足楼主需求
    zzzmode
        32
    zzzmode  
       May 30, 2019
    kong 网关
    opengps
        33
    opengps  
       May 30, 2019
    如果是单机应用,服务器上装个安全狗之类的防护工具,可以对所有请求整体频率起效果。
    如果只是某个接口调用,套了 cdn 则被忽视,不套上 cdn 的业务需要做个公共缓存统计,记录一个列表,每次请求顺便释放掉超时的缓存对象
    opengps
        34
    opengps  
       May 30, 2019
    如果是单机单接口,那么可以利用系统自带缓存,或者本机 memcached 缓存做个计数(取出结果非等于 1 则++,等于 null 则赋值 1 ),超时时间就设置 1 分钟
    gaius
        35
    gaius  
       May 30, 2019
    这问题我遇到过,1 时 0 分 1s 发了 500 个,2 时 0 分 2s 又发了 500,从 1s 到 2s 的这个时间窗口却是 1 小时发了 1000。
    如果消费还有优先级的话,还再麻烦点。
    gscoder
        36
    gscoder  
       May 30, 2019
    和限流是一样的方法:漏桶算法、令牌桶算法、滑动窗口算法。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   775 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 78ms · UTC 21:36 · PVG 05:36 · LAX 14:36 · JFK 17:36
    ♥ Do have faith in what you're doing.