Take you to understand what is limiting

Foreword

Only the head can become strong.

Text has been included to my GitHub repository, welcome Star: github.com/ZhongFuChen...

Before learning when this kind of thing can not be in contact with high concurrency / high flow, of course, is not so limiting contact of the. When looking at the project company, found to be useful to limit the flow (RateLimiter), incidentally understand wave.

First, limiting the basics of presentation

Why would limit, I believe I do not have much to say.

  • For example, I went to a restaurant for dinner on weekends, but too many people , I can only go to the front desk to get a number, and other number to me when to get into a restaurant for dinner. If the hotel is not limiting how to do? A meal to the point, people rushed inside, and they can not deal with so many restaurants crowd, it is easy to have an accident (hotel filled with people, no way. The hotel staff broke down, handle, however)
  • Back to the code in the world is the same, the server can handle a limited number of requests, particularly if a large volume of requests, we do need to limit the flow (either let the request to wait, or put the request to throw)

Limiting

In the code of the world, there are two common limiting algorithm:

  • Token bucket algorithm
  • Leaky Bucket Algorithm

1.1 What is a leaky bucket

For example, now I have a bucket, I can hold a piece of green water capacity, if I can hold over capacity in, go down to pour buckets inside, it will overflow (limiting):

Buckets

We currently know is:

  • Bucket capacity is fixed (FIG green piece is)
  • It exceeds the capacity of the bucket will overflow (or wait, either directly discarded)

OK, now we have to dig a hole in a bucket, so that water can flow out from inside the cave:

He dug a hole, the water flow out from the hole

Bucket size of the hole is fixed, the rate of water flow out from the hole is fixed .

So conclude the parameters required by the algorithm to two:

  • Bucket capacity
  • Leakage rate

Leaky Bucket algorithm has two kinds of realization:

  1. Bursty traffic is not allowed : if the water rate greater than the rate of water directly discard excess water. For example, I can hold the bucket capacity of 100L, but my water bucket rate is 10L / s. At this point, if there are 100L / s of water came in, I just let 10L of water into the bucket, and the rest are limiting. ( Defining a requested speed )
  2. Allow certain burst traffic situation: my bucket can hold 100L, if now my bucket is empty, then this could 100L of water into my bucket. I'm at a rate of 10L / s flow out of these, if there 100L of water came in, only the current limit.

After the above analysis we know:

Leaky bucket algorithm may burst traffic on the network a smooth (because leakage rate is fixed)

1.2 What is a token bucket algorithm

Now I have another bucket, the bucket is not used to hold water, used to hold the token:

Bucket filled with tokens

Token will be thrown into the bucket inside a certain rate, for example, one second I threw 10 tokens into the bucket:

At a rate thrown into the token bucket

Token bucket can hold the number of capped, such as my bucket can only hold up to 1000 tokens.

For each request, it will take a token bucket to

  • For example, this second I have a 1001 request, I went inside to take the 1001 token bucket, then two situations may occur:
    • No bucket inside 1001 tokens, only 1000, it did not get the token request can only be blocked (wait)
    • 1,001 tokens inside the bucket, all the requests can be executed.

Token bucket algorithm supports bursty traffic on the network

** difference between the drain and the tub token buckets: ** estimated from the above examples we can see, the only leaky bucket at a fixed rate to process the request, and the maximum number of token bucket token buckets to process the request

Two, RateLimiter use

RateLimiter is a limiting component of Guava, my side of this system will have to use current limiting components, very convenient to use.

The introduction of pom-dependent:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>20.0</version>
</dependency>
复制代码

RateLimiter it is a token bucket algorithm is, API is very simple, look at the following Demo:

public static void main(String[] args) {
        //线程池
        ExecutorService exec = Executors.newCachedThreadPool();
        //速率是每秒只有3个许可
        final RateLimiter rateLimiter = RateLimiter.create(3.0);

        for (int i = 0; i < 100; i++) {
            final int no = i;
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    try {
                        //获取许可
                        rateLimiter.acquire();
                        System.out.println("Accessing: " + no + ",time:"
                                + new SimpleDateFormat("yy-MM-dd HH:mm:ss").format(new Date()));

                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                }
            };
            //执行线程
            exec.execute(runnable);
        }
        //退出线程池
        exec.shutdown();
    }
复制代码

We can see from the results, it can be performed only three per second:

The implementation of three per second

Third, limiting distributed

RateLimiter is limiting a stand-alone component, if the application is distributed, then how to do?

May be used Redis + Lua way to achieve substantially the lua script code is as follows:

local key = "rate.limit:" .. KEYS[1] --限流KEY
local limit = tonumber(ARGV[1])        --限流大小
local current = tonumber(redis.call('get', key) or "0")
if current + 1 > limit then --如果超出限流大小
  return 0
else  --请求数+1,并设置1秒过期
  redis.call("INCRBY", key,"1")
   redis.call("expire", key,"1")
   return current + 1
end
复制代码

Java code is as follows:

public static boolean accquire() throws IOException, URISyntaxException {
    Jedis jedis = new Jedis("127.0.0.1");
    File luaFile = new File(RedisLimitRateWithLUA.class.getResource("/").toURI().getPath() + "limit.lua");
    String luaScript = FileUtils.readFileToString(luaFile);

    String key = "ip:" + System.currentTimeMillis()/1000; // 当前秒
    String limit = "5"; // 最大限制
    List<String> keys = new ArrayList<String>();
    keys.add(key);
    List<String> args = new ArrayList<String>();
    args.add(limit);
    Long result = (Long)(jedis.eval(luaScript, keys, args)); // 执行lua脚本,传入参数
    return result == 1;
}
复制代码

Explanation:

  • Java code passed in key parameters and maximum limit limit into the lua script
  • Execute lua script (lua script to determine whether the current key exceeds the maximum limit limit)
    • If so, it returns 0 (limiting)
    • If not, the returns 1 (the program continues)

Reference Source:

More information Reference:

At last

Willing output of dry cargo of Java technology public number: Java3y . A public number more than 200 original articles technical articles, massive video resources, beautiful mind map, attention can get!

Forwarded to the circle of friends is the biggest support for me!

I think the article is well written, points praise !

Guess you like

Origin juejin.im/post/5d8036a3e51d4561ff6668c3