"古之欲明明德于天下者, 先治其国; 欲治其国者, 先齐其家; 欲齐其家者, 先修其身; 欲修其身者, 先正其心; 欲正其心者, 先诚其意; 欲诚其意者, 先致其知, 致知在格物. 物格而后知至, 知至而后意诚, 意诚而后心正, 心正而后身修, 身修而后家齐, 家齐而后国治, 国治而后天下平."--《礼记. 大学》
在应对秒杀, 大促, 双 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:-从-Hystrix-迁移到-Sentinel
来源: https://www.cnblogs.com/davidwang456/p/11363211.html