liaojl
V2EX  ›  Java

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

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

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

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