“古之欲明明德于天下者,先治其国;欲治其国者,先齐其家;欲齐其家者,先修其身;欲修其身者,先正其心;欲正其心者,先诚其意;欲诚其意者,先致其知,致知在格物。物格而后知至,知至而后意诚,意诚而后心正,心正而后身修,身修而后家齐,家齐而后国治,国治而后天下平。”--《礼记·大学》

在应对秒杀、大促、双 11、618 等高性能压力的场景时,限流已经成为了标配技术解决方案,为保证系统的平稳运行起到了关键性的作用。不管应用场景是哪种,限流无非就是针对超过预期的流量,通过预先设定的限流规则选择性的对某些请求进行限流“熔断”。

根据修身、齐家、治国平天下的理念,限流与熔断要先从小点着手,即先对单机进行限流与熔断,然后对微服务小集群做限流与熔断,最后是对整个流程的服务集群做限流与熔断。

1. 限流

1.1 单机限流(修身)

  修身

a>>限制并发量

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SemaphoreTest {
 private static final int THREAD_COUNT = 30;
 private static ExecutorService threadPool = Executors
 .newFixedThreadPool(THREAD_COUNT);
 private static Semaphore s = new Semaphore(10);
 public static void main(String[] args) {
 for (int i = 0; i < THREAD_COUNT; i++) {
 threadPool.execute(new Runnable() {
 @Override
 public void run() {
 try {
 s.acquire();
 System.out.println(Thread.currentThread().getName());
 Thread.sleep(5000);
 System.out.println("--------------");
 s.release();
 } catch (InterruptedException e) {
 }
 }
 });
 }
 threadPool.shutdown();
 }
}

 

b>>计数器,以CountDownLatch为例

import java.util.concurrent.CountDownLatch;
public class CountDownLatchTest2 {
 public static void main(String[] args) {
 // 创建计数器,初始化为2
 final CountDownLatch latch = new CountDownLatch(2);
 new Thread(() -> {
 try {
 System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");
 Thread.sleep(3000);
 System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");
 latch.countDown();// 减一
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 }).start();
 new Thread(() -> {
 try {
 System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");
 Thread.sleep(3000);
 System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");
 latch.countDown();
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 }).start();
 try {
 System.out.println("等待2个子线程执行完毕...");
 // 阻塞
 latch.await();
 System.out.println("2个子线程已经执行完毕");
 System.out.println("继续执行主线程");
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 }
}

c>>guava RateLimiter

public void test()
{
 /**
 * 创建一个限流器,设置每秒放置的令牌数:2个。速率是每秒可以2个的消息。
 * 返回的RateLimiter对象可以保证1秒内不会给超过2个令牌,并且是固定速率的放置。达到平滑输出的效果
 */
 RateLimiter r = RateLimiter.create(2);
 while (true)
 {
 /**
 * acquire()获取一个令牌,并且返回这个获取这个令牌所需要的时间。如果桶里没有令牌则等待,直到有令牌。
 * acquire(N)可以获取多个令牌。
 */
 System.out.println(r.acquire());
 }
}

 

1.2 分布式限流(齐家)

                齐家

a>> nginx

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s;
server { 
 location / { 
 limit_req zone=mylimit;
 }
}

 

b>>api-gateway+redis限流

https://github.com/wangzheng0822/ratelimiter4j

1.3 大流程限流(治国平天下)

可以从防火墙,cdn,路由器,api网关等做限流

                              治国平天下

2. 熔断对比

熔断处理逻辑类似,可以利用一些现成的框架,如Sentinel、Hystrix、resilience4j等。

功能对比

熔断对比

参考文献:

【1】https://mp.weixin.qq.com/s?__biz=MjM5MDE0Mjc4MA==&mid=2651008444&idx=1&sn=a579c3ceb143ea30930bd4c6d4a8d7e2&chksm=bdbed5ef8ac95cf93e71c5393f08e3b97a7e19e8232ce3872231f2cae74f7a19ab15501aeb44&scene=27#wechat_redirect

【2】https://mp.weixin.qq.com/s?__biz=MzIwMzY1OTU1NQ==&mid=2247484306&idx=1&sn=b6c1b7b9d7c57bbb9f82ec451bcda867&chksm=96cd43dea1bacac8a24cde429146f69dba8bb15c5c9c3fe9adfe858d9a4349cc127fbfa84a8c&scene=27#wechat_redirect

【3】https://github.com/alibaba/Sentinel/wiki/Guideline:-%E4%BB%8E-Hystrix-%E8%BF%81%E7%A7%BB%E5%88%B0-Sentinel

posted on 2019-08-16 12:56  一天不进步,就是退步  阅读(480)  评论(0编辑  收藏  举报