专业的编程技术博客社区

网站首页 > 博客文章 正文

从修身齐家治国平天下谈分布式系统中的限流与熔断

baijin 2024-08-27 11:34:53 博客文章 6 ℃ 0 评论

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

在应对秒杀、大促、双 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等。

功能对比

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表