高并发后端设计-限流篇

转载 2018年04月15日 00:00:00

系统在设计之初就会有一个预估容量,长时间超过系统能承受的TPS/QPS阈值,系统可能会被压垮,最终导致整个服务不够用。为了避免这种情况,我们就需要对接口请求进行限流。 

限流的目的是通过对并发访问请求进行限速或者一个时间窗口内的的请求数量进行限速来保护系统,一旦达到限制速率则可以拒绝服务、排队或等待。 

常见的限流模式有控制并发和控制速率,一个是限制并发的数量,一个是限制并发访问的速率,另外还可以限制单位时间窗口内的请求数量。

控制并发数量

属于一种较常见的限流手段,在实际应用中可以通过信号量机制(如Java中的Semaphore)来实现。 
举个例子,我们对外提供一个服务接口,允许最大并发数为10,代码实现如下:

public class DubboService {    private final Semaphore permit = new Semaphore(10, true);    public void process(){        try{
            permit.acquire();            //业务逻辑处理

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            permit.release();
        }
    }
}

在代码中,虽然有30个线程在执行,但是只允许10个并发的执行。Semaphore的构造方法Semaphore(int permits) 接受一个整型的数字,表示可用的许可证数量。Semaphore(10)表示允许10个线程获取许可证,也就是最大并发数是10。Semaphore的用法也很简单,首先线程使用Semaphore的acquire()获取一个许可证,使用完之后调用release()归还许可证,还可以用tryAcquire()方法尝试获取许可证。

控制访问速率

在我们的工程实践中,常见的是使用令牌桶算法来实现这种模式,其他如漏桶算法也可以实现控制速率,但在我们的工程实践中使用不多,这里不做介绍,读者请自行了解。

在Wikipedia上,令牌桶算法是这么描述的:

  1. 每过1/r秒桶中增加一个令牌。

  2. 桶中最多存放b个令牌,如果桶满了,新放入的令牌会被丢弃。

  3. 当一个n字节的数据包到达时,消耗n个令牌,然后发送该数据包。

  4. 如果桶中可用令牌小于n,则该数据包将被缓存或丢弃。

令牌桶控制的是一个时间窗口内通过的数据量,在API层面我们常说的QPS、TPS,正好是一个时间窗口内的请求量或者事务量,只不过时间窗口限定在1s罢了。以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。令牌桶的另外一个好处是可以方便的改变速度,一旦需要提高速率,则按需提高放入桶中的令牌的速率。

在我们的工程实践中,通常使用Guava中的Ratelimiter来实现控制速率,如我们不希望每秒的任务提交超过2个:

//速率是每秒两个许可final RateLimiter rateLimiter = RateLimiter.create(2.0);

void submitTasks(List tasks, Executor executor) {    for (Runnable task : tasks) {
        rateLimiter.acquire(); // 也许需要等待
        executor.execute(task);
    }
}

控制单位时间窗口内请求数

某些场景下,我们想限制某个接口或服务 每秒/每分钟/每天 的请求次数或调用次数。例如限制服务每秒的调用次数为50,实现如下:

import com.google.common.cache.CacheBuilder;import com.google.common.cache.CacheLoader;import com.google.common.cache.LoadingCache;import java.util.concurrent.ExecutionException;import java.util.concurrent.TimeUnit;import java.util.concurrent.atomic.AtomicLong;

    private LoadingCache<Long, AtomicLong> counter =
            CacheBuilder.newBuilder()                    .expireAfterWrite(2, TimeUnit.SECONDS)                    .build(new CacheLoader<Long, AtomicLong>() {
                        @Override
                        public AtomicLong load(Long seconds) throws Exception {
                            return new AtomicLong(0);
                        }
                    });

    public static long permit = 50;

    public ResponseEntity getData() throws ExecutionException {

        //得到当前秒
        long currentSeconds = System.currentTimeMillis() / 1000;
        if(counter.get(currentSeconds).incrementAndGet() > permit) {
            return ResponseEntity.builder().code(404).msg("访问速率过快").build();
        }
        //业务处理

    }


关于限流部分到此就结束了,下一篇将介绍降级和熔断机制。


Java高级架构 干货|学习640?wx_fmt=png640?wx_fmt=png长按,识别二维码,加关注




高并发后端设计-限流篇

系统在设计之初就会有一个预估容量,长时间超过系统能承受的TPS/QPS阈值,系统可能会被压垮,最终导致整个服务不够用。为了避免这种情况,我们就需要对接口请求进行限流。限流的目的是通过对并发访问请求进行...
  • FX_SKY
  • FX_SKY
  • 2016年11月20日 17:22
  • 6700

高并发后端设计之《限流》

系统在设计之初就会有一个预估容量,长时间超过系统能承受的TPS/QPS阈值,(其中TPS是每秒内的事务数,比如执行了dml操作,那么相应的tps会增加;QPS是指每秒内查询次数,比如执行了select...
  • USTC_Zn
  • USTC_Zn
  • 2017年10月17日 21:19
  • 166

高并发之限流

在应对高并发场景的时候,我们会采用多种方式来保证系统的高可用,尽量保证用户体验。而其中我们最常用的三把刀,就是限流、降级、缓存等。缓存,我们常用的可以用如redis之类的分布式缓存进行处理。降级,可以...
  • Snail_Ren
  • Snail_Ren
  • 2017年09月15日 15:30
  • 331

聊聊高并发系统之限流特技一

原文链接:http://www.jianshu.com/p/2596e559db5c
  • mbugatti
  • mbugatti
  • 2017年03月03日 11:03
  • 871

高并发限流(一)——简介

1.?? ??????????????????????????? ????????????????????????????????????????????mysql???????db?????????...
  • xxcupid
  • xxcupid
  • 2016年07月24日 18:39
  • 1949

多线程安全的滑动窗口设计实现

滑动窗口是日志模块重要的数据结构,用于日志发送接收以及日志索引查询,和组内同学讨论了的多线程安全的滑动窗口设计,有三种实现方案,写此文档记录下。...
  • zhang_shuai_2011
  • zhang_shuai_2011
  • 2014年09月24日 14:14
  • 1617

高并发限流(二)——应用举例

1.?????????????? 1.????AtomicLong??????????? try { if(atomic.incrementAndGet() > ???) { ...
  • xxcupid
  • xxcupid
  • 2016年07月24日 21:44
  • 1980

Java高并发系统的限流策略

概要 在大数据量高并发访问时,经常会出现服务或接口面对暴涨的请求而不可用的情况,甚至引发连锁反映导致整个系统崩溃。此时你需要使用的技术手段之一就是限流,当请求达到一定的并发数或速率,就进行等待、排...
  • syc001
  • syc001
  • 2017年06月02日 10:25
  • 3214

高并发系统之限流特技

在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流。缓存的目的是提升系统访问速度和增大系统能处理的容量,可谓是抗高并发流量的银弹;而降级是当服务出问题或者影响到核心流程的性能则需要暂时屏蔽掉,...
  • g_hongjin
  • g_hongjin
  • 2016年06月12日 21:49
  • 8072

谈谈高并发系统的限流

http://www.cnblogs.com/haoxinyue/p/6792309.html?utm_source=tuicool&utm_medium=referral 开涛大神在博客中...
  • u011001084
  • u011001084
  • 2017年05月02日 09:15
  • 275
收藏助手
不良信息举报
您举报文章:高并发后端设计-限流篇
举报原因:
原因补充:

(最多只允许输入30个字)