zoukankan      html  css  js  c++  java
  • Java 对IP请求进行限流.

    高并发系统下, 有三把利器 缓存 降级 限流.

    • 缓存: 将常用数据缓存起来, 减少数据库或者磁盘IO
    • 降级: 保护核心系统, 降低非核心业务请求响应
    • 限流: 在某一个时间窗口内对请求进行限速, 保护系统

     本文主要介绍限流, 常见限流算法中又分为计数器算法, 漏桶算法, 令牌桶算法.

    计数器算法

    比较简单, 直接用一个map + counter即可实现. 请求来了, 以IP为key,

    查询下之前响应次数, 如果调用次数超出MAX_COUT, 返回失败, 属于简单粗暴型选手.

    漏桶算法

    请求全部进入漏桶, 漏桶恒定速率输出反馈. 这样可以保证数据传输平滑,

    但是无法预防突发大量请求, 一秒来了100个请求, 都要阻塞排队, 从小水管输出数据.

     

    令牌桶算法

    令牌桶是以固定速度往桶里存令牌, 例如一秒存1000个令牌, 业务请求来了, 直接从桶里获取令牌响应输出.

    跟漏桶的差异在于, 他可以预存令牌, 如果一秒钟来了100个请求, 桶里有100个令牌,

    那么可以立刻响应给客户端, 而不是排队输出.

     

    令牌桶的实现

    guava中提供了令牌桶的一个封装实现RateLimiter, 可以直接调用, 省的我们自己包装ConcurrentHashMap + Timer.

    我们预设的场景是服务器端提供一个API供不同客户端查询, 要限流每个IP每秒只能调用两次该API.

    首先要定义一个服务器端的缓存, 定期清理即可, 缓存 IP : 令牌桶

    复制代码
     1     // 根据IP分不同的令牌桶, 每天自动清理缓存
     2     private static LoadingCache<String, RateLimiter> caches = CacheBuilder.newBuilder()
     3             .maximumSize(1000)
     4             .expireAfterWrite(1, TimeUnit.DAYS)
     5             .build(new CacheLoader<String, RateLimiter>() {
     6                 @Override
     7                 public RateLimiter load(String key) throws Exception {
     8                     // 新的IP初始化 (限流每秒两个令牌响应)
     9                     return RateLimiter.create(2);
    10                 }
    11             });
    复制代码

    然后在业务代码中进行限流调用

    复制代码
     1     private static void login(int i) throws ExecutionException {
     2         // 模拟IP的key
     3         String ip = String.valueOf(i).charAt(0) + "";
     4         RateLimiter limiter = caches.get(ip);
     5 
     6         if (limiter.tryAcquire()) {
     7             System.out.println(i + " success " + new SimpleDateFormat("HH:mm:ss.sss").format(new Date()));
     8         } else {
     9             System.out.println(i + " failed " + new SimpleDateFormat("HH:mm:ss.sss").format(new Date()));
    10         }
    11     }
    复制代码

    模拟客户端调用

    1         for (int i = 0; i < 1000; i++) {
    2             // 模拟实际业务请求
    3             Thread.sleep(100);
    4             login(i);
    5         }

    完整代码

    View Code

     

  • 相关阅读:
    ZOJ 3818 Pretty Poem
    HDU 4597 Play Game
    HDU 4497 GCD and LCM
    CSU 1335 高桥和低桥
    UVA 10791 Minimum Sum LCM
    CSU 1119 Collecting Coins
    CSU 1120 病毒
    UVA 12169 Disgruntled Judge
    HDU 1301 Jungle Roads
    POJ 1258 Agri-Net
  • 原文地址:https://www.cnblogs.com/tiancai/p/9622986.html
Copyright © 2011-2022 走看看