加入收藏 | 设为首页 | 会员中心 | 我要投稿 湖南网 (https://www.hunanwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

漫衍式限流,你想知道的都在这里

发布时间:2019-04-25 04:35:15 所属栏目:教程 来源:儒雅程序员
导读:媒介 在一个高并发体系中对流量的把控长短常重要的,当庞大的流量直接哀求到我们的处事器上没多久就也许造成接口不行用,不处理赏罚的话乃至会造成整个应用不行用。 好比最近就有个这样的需求,我作为客户端要向kafka出产数据,而kafka的斲丧者则再绵绵不断的

Java 中的挪用逻辑:

  1. --lua 下标从 1 开始 
  2. -- 限流 key 
  3. local key = KEYS[1] 
  4. -- 限流巨细 
  5. local limit = tonumber(ARGV[1]) 
  6. -- 获取当前流量巨细 
  7. local curentLimit = tonumber(redis.call('get', key) or "0") 
  8. if curentLimit + 1 > limit then 
  9.  -- 到达限流巨细 返回 
  10.  return 0; 
  11. else 
  12.  -- 没有到达阈值 value + 1 
  13.  redis.call("INCRBY", key, 1) 
  14.  redis.call("EXPIRE", key, 2) 
  15.  return curentLimit + 1 
  16. end 

以是只必要在必要限流的处所挪用该要领对返回值举办判定即可到达限流的目标。

虽然这只是操作 Redis 做了一个粗暴的计数器,假如想实现相同于上文中的令牌桶算法可以基于 Lua 自行实现。

Builder 构建器

在计划这个组件时想只管的提供应行使者清楚、可读性、不易堕落的 API。

好比第一步,怎样构建一个限流工具。

最常用的方法天然就是结构函数,假若有多个域则可以回收重叠结构器的方法:

  1. public A(){} 
  2. public A(int a){} 
  3. public A(int a,int b){} 

弱点也是显而易见的:假如参数过多会导致难以阅读,乃至假如参数范例同等的环境下客户端颠倒了次序,但不会引起告诫从而呈现难以猜测的功效。

第二种方案可以回收 JavaBean 模式,操作 setter 要领举办构建:

  1. A a = new A(); 
  2. a.setA(a); 
  3. a.setB(b); 

这种方法清楚易读,但却轻易让工具处于纷歧致的状态,使工具处于线程不安详的状态。

以是这里回收了第三种建设工具的方法,构建器:

  1. public class RedisLimit { 
  2.  private JedisCommands jedis; 
  3.  private int limit = 200; 
  4.  private static final int FAIL_CODE = 0; 
  5.  /** 
  6.  * lua script 
  7.  */ 
  8.  private String script; 
  9.  private RedisLimit(Builder builder) { 
  10.  this.limit = builder.limit ; 
  11.  this.jedis = builder.jedis ; 
  12.  buildScript(); 
  13.  } 
  14.  /** 
  15.  * limit traffic 
  16.  * @return if true 
  17.  */ 
  18.  public boolean limit() { 
  19.  String key = String.valueOf(System.currentTimeMillis() / 1000); 
  20.  Object result = null; 
  21.  if (jedis instanceof Jedis) { 
  22.  result = ((Jedis) this.jedis).eval(script, Collections.singletonList(key), Collections.singletonList(String.valueOf(limit))); 
  23.  } else if (jedis instanceof JedisCluster) { 
  24.  result = ((JedisCluster) this.jedis).eval(script, Collections.singletonList(key), Collections.singletonList(String.valueOf(limit))); 
  25.  } else { 
  26.  //throw new RuntimeException("instance is error") ; 
  27.  return false; 
  28.  } 
  29.  if (FAIL_CODE != (Long) result) { 
  30.  return true; 
  31.  } else { 
  32.  return false; 
  33.  } 
  34.  } 
  35.  /** 
  36.  * read lua script 
  37.  */ 
  38.  private void buildScript() { 
  39.  script = ScriptUtil.getScript("limit.lua"); 
  40.  } 
  41.  /** 
  42.  * the builder 
  43.  * @param <T> 
  44.  */ 
  45.  public static class Builder<T extends JedisCommands>{ 
  46.  private T jedis = null ; 
  47.  private int limit = 200; 
  48.  public Builder(T jedis){ 
  49.  this.jedis = jedis ; 
  50.  } 
  51.  public Builder limit(int limit){ 
  52.  this.limit = limit ; 
  53.  return this; 
  54.  } 
  55.  public RedisLimit build(){ 
  56.  return new RedisLimit(this) ; 
  57.  } 
  58.  } 

(编辑:湖南网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读