Zookeeper 如何实现分布式速率限制器?

1sbrub3j  于 2022-12-09  发布在  Apache
关注(0)|答案(5)|浏览(170)

比如说,我有P个进程在N台物理机器上运行某个业务逻辑,这些进程调用某个Web服务S,我想确保所有P个进程每秒对服务S的调用不超过X次。
如何实施这样的解决方案?
GoogleGuava的速率限制器对于在单机上运行的进程效果很好,但在分布式设置中效果不佳。
是否有任何标准的、现成可用的JAVA解决方案?[可能基于zookeeper]
谢谢你!

ddhy6vgd

ddhy6vgd1#

Bucket4j是“token-bucket”速率限制算法的java实现。它在本地和分布式(在JCache之上)都能工作。对于分布式用例,您可以自由选择任何JCache实现,如Hazelcast或Apache Ignite。请参见在集群中使用Bucket 4j的示例。

odopli94

odopli942#

I have been working on an opensource solution for these kind of problems.
Limitd is a "server" for limits. The limits are implemented using the Token Bucket Algorithm .
Basically you define limits in the service configuration like this:

buckets:
  "request to service a":
     per_minute: 10
  "request to service b":
     per_minute: 5

The service is run as a daemon listening on a TCP/IP port.
Then your application does something along these lines:

var limitd = new Limitd('limitd://my-limitd-address');

limitd.take('request to service a', 'app1' 1, function (err, result) {
  if (result.conformant) {
    console.log('everything is okay - this should be allowed');
  } else {
    console.error('too many calls to this thing');
  }
});

We are currently using this for rate-limiting and debouncing some application events.
The server is on:
https://github.com/auth0/limitd
We are planning to work on several SDKs but for now we only have node.js and partially implemented go:
https://github.com/limitd

lhcgjxsq

lhcgjxsq3#

https://github.com/jdwyah/ratelimit-java提供了分布式速率限制,应该做到这一点。您可以将您的限制配置为S每秒/分钟等,并选择突发大小/重新填充速率的漏桶是在封面。

g52tjvyc

g52tjvyc4#

Java中的简单速率限制,您希望每3秒实现3个事务的并发。如果您希望将此集中化,则将令牌数组存储在elasticache或任何数据库中。并且,您还必须实现一个锁定标志来代替同步块。

import java.util.Date;

public class RateLimiter implements Runnable {

private long[] tokens = new long[3];

public static void main(String[] args) {
    // TODO Auto-generated method stub
    RateLimiter rateLimiter = new RateLimiter();
    for (int i=0; i<20; i++) {
        Thread thread = new Thread(rateLimiter,"Thread-"+i );
        thread.start();
    }
    
}

@Override
public void run() {
    // TODO Auto-generated method stub
    long currentStartTime = System.currentTimeMillis();
    while(true) {
    
    if(System.currentTimeMillis() - currentStartTime > 100000 ) {
        throw new RuntimeException("timed out");
    }else {
        if(getToken()) {
        System.out.println(Thread.currentThread().getName() + 
                " at " + 
                new Date(System.currentTimeMillis()) + " says hello");
        break;
        }
    }
    
    }
    
}

synchronized private boolean getToken() {
    // TODO Auto-generated method stub
    
    for (int i = 0; i< 3; i++) {
        if(tokens[i] == 0 || System.currentTimeMillis() - tokens[i] > 3000) {
            tokens[i] = System.currentTimeMillis();
            return true;
        }
    }
    
    return false;
}

}
yhived7q

yhived7q5#

因此,对于所有分布式速率限制架构,您需要一个后端存储作为true的单一来源来跟踪请求的数量。出于方便,您可以使用zookeeper作为内存中的数据存储,尽管也有更好的选择,如Redis。

相关问题