如何保证系统的高可用?
限流把好入口限流是指在一段时间内限制系统的输入/输出流量以达到保护系统的目的。如果流量超过设定阈值则采取拒绝、排队或降级等策略限流算法计数器算法这是最容易理解和实现的算法假设一个接口1s中最多请求100次。最开始设置一个计数器count0来一个请求count11s之内count100的请求可以正常访问count100的请求则被拒绝1s之后count被重置为0重新开始计数当然这种方式有个弊端1s内只有最开始的100个请求能正常访问后面的请求都不能正常访问即突刺现象。此时我们就可以用滑动窗口算法来解决这个问题例如把1s分成5个时间段每个时间段能正常请求20次。漏桶算法漏桶算法参考家里使用的漏斗你就能明白了往漏斗里面倒水不论倒多少水下面出水的速率是恒定的。当漏斗满了多余的水就被直接丢弃了。类比流量每秒处理的速率是恒定的如果有大量的流量过来就先放到漏斗里面。当漏斗也满了请求则被丢弃。实现用队列保存请求用ScheduledThreadPoolExecutor支持定时任务的线程池来定时从队列中取请求来执行令牌桶算法令牌桶算法可以说是对漏桶算法的改进。漏桶算法能限制请求的速率。而令牌桶算法在限制请求速率的同时还允许一定程度的突发调用过程如下一直放令牌如果令牌桶达到上限则丢弃令牌假设每秒放10个可以应对一定程度的流量激增如此时令牌桶有100个令牌突然发生200次调用则此时最开始的100次请求可以正常调用后续的请求才会以10个/s的速率来调用实现用队列保存令牌用ScheduledThreadPoolExecutor来定时放令牌一般使用google提供的guava工具包即可dependencygroupIdcom.google.guava/groupIdartifactIdguava/artifactIdversion18.0/version/dependency// 每秒生成2个令牌RateLimiterrateLimiterRateLimiter.create(2);for(inti0;i6;i){newThread(()-{// 获得令牌rateLimiter.acquire();System.out.println(LocalDateTime.now());}).start();}输出为如下可以看到每秒执行2个请求2020-04-11T20:54:45.254 2020-04-11T20:54:45.554 2020-04-11T20:54:46.054 2020-04-11T20:54:46.555 2020-04-11T20:54:47.068 2020-04-11T20:54:47.554rateLimiter提供了acquire()和tryAcquire()方法acquire()方法如果没有可用令牌会一直阻塞到获得令牌tryAcquire()方法如果没有可用令牌则直接返回false可以设置超时获取漏桶算法适用于限制数据的平均传输速率并平滑处理这些数据的场景。令牌桶则更灵活一点即限制数据的平均传输速率又允许一定程度的突发调用技术实现方案层级方案网关层限流在 Nginx、Spring Cloud Gateway、Kong 等网关处统一限制。Nginx 原生提供了基于漏桶算法的 limit_req 模块单机限流Guava 的 RateLimiter基于令牌桶Resilience4j 的 AtomicRateLimiter 基于令牌桶分布式限流Redisson 的 RRateLimiter基于令牌桶结合滑动窗口的思想实现的降级弃车保帅的艺术降级是指在系统由于高并发或故障导致资源不足时主动屏蔽/关停一部分非核心功能将宝贵的资源留给核心业务降级通常与限流、熔断配合使用作为限流被拦截后、或者熔断打开后的后备方案也可以人工主动触发按触发时机分类自动降级当触发限流、熔断、网络超时、资源异常如线程池满时代码自动捕捉异常并执行预设的 Fallback 方法例如返回内存缓存数据、返回空列表、或者返回友好提示“系统繁忙请稍后再试”。人工降级在双十一等大促前通过配置中心如 Nacos、Apollo下发开关主动关闭非核心业务如暂停历史订单查询、暂停写评论功能、关闭某些推荐算法。熔断防止级联雪崩熔断机制借鉴了电网中的“保险丝”。当某个下游服务由于网络故障、数据库死锁等原因出现高延迟或大量报错时上游服务继续调用它只会导致线程积压最终引发雪崩效应。熔断的目的就是及时切断故障调用状态机模型熔断器内部维护了一个状态机包含三个状态Closed关闭状态正常状态。所有请求都放行。熔断器会统计这一期间的错误率或慢调用比例如果达到设定阈值则转换为 Open 状态。Open打开状态熔断状态。所有请求直接被拦截不再调用下游服务而是直接触发降级逻辑Fallback。同时开启一个时间窗口如 5 秒。Half-Open半开状态时间窗口到期后熔断器进入半开状态允许少量请求通过去尝试调用下游服务如果这些请求成功说明下游服务已恢复熔断器回到 Closed 状态。如果这些请求依然失败说明服务未恢复熔断器重新回到 Open 状态并重新计时。关键配置项配置项作用滑动窗口大小统计过去多少个请求或多少秒内的数据。错误率/慢调用比例阈值如错误率达到 50%或者耗时超过 2 秒的慢调用比例达到 40%最小请求数在滑动窗口内必须至少有多少个请求才会触发熔断计算防止样本太少导致误判技术方案实现框架介绍Resilience4j基于 Java 8 函数式编程Sentinel支持熔断降级可配置慢调用比例或异常比例Hystrix已停止维护不推荐新项目曾经的标杆我们还可以在业务层面实现熔断