比如DB连接失败,文件读取失败等
比如:用户经常会在京东、淘宝、天猫、拼多多等平台上参与商品的秒杀、限时抢购等优惠活动,也会在节假日使用12306 抢火车票、高铁票,甚至有时候还要帮助同事、朋友为他们家小孩拉投票、刷票,这些场景都无一例外的会引起服务器流量的暴涨,导致网页无法显示、APP反应慢、功能无法正常运转,甚至会引起整个网站的崩溃(服务雪崩)。
在微服务项目中,经常存在服务A调用服务B,服务B又调用服务C等微服务级联调用的场景,当服务C出现故障,服务B和服务A都会跟着出现故障,因为它们之间存在调用链关系;有时候调用链会很长并且很复杂,比如服务A不仅调用了服务B,还调用了服务H、服务I、服务J等等,同时服务A调用链的最长链条终端有可能是从服务C、服务D一直到服务Z,这种调用复杂的调用链条一旦出现故障,有可能直接让整个微服务体系都无法提供服务,造成的影响是致命的。这种由于调用链中某一个节点出现故障而引发的级联故障,称为服务雪崩,也称为级联故障、级联失效。
异常没处理,我们处理一下异常就可以,而对于另外两个原因导致的服务雪崩,我们应该怎么解决呢或者说应该怎么建立容错机制呢?
常见的容错机制有隔离、超时、限流、熔断、降级等。
隔离
它是指将系统按照一定的原则划分为若干个服务模块,各个模块之间相对独立,无强依赖。当有故障发生时,能将问题和影响隔离在某个模块内部,而不扩散风险,不波及其它模块,不影响整体的 系统服务。常见的隔离方式有:线程池隔离和信号量隔离。
超时
在上游服务调用下游服务的时候,设置一个最大响应时间,如果超过这个时间,下游未作出反应, 就断开请求,释放掉线程。
限流
限流就是限制系统的输入和输出流量已达到保护系统的目的。为了保证系统的稳固运行,一旦达到 的需要限制的阈值,就需要限制流量并采取少量措施以完成限制流量的目的。
熔断
在互联网系统中,当下游服务因访问压力过大而响应变慢或失败,上游服务为了保护系统整体的可用性,可以暂时切断对下游服务的调用。这种牺牲局部,保全整体的措施就叫做熔断。
降级
降级其实就是为服务提供一个托底方案,一旦服务无法正常调用,就使用托底方案。
Hystrix
Hystrix是由Netflix开源的一个延迟和容错库,用于隔离访问远程系统、服务或者第三方库,防止级联失败,从而提升系统的可用性与容错性。
Resilience4J
Resilicence4J一款非常轻量、简单,并且文档非常清晰、丰富的熔断工具,这也是Hystrix官方推荐的替代产品。不仅如此,Resilicence4j还原生支持Spring Boot 1.x/2.x,而且监控也支持和prometheus等多款主流产品进行整合。
Sentinel
Sentinel 是阿里巴巴开源的一款断路器实现,是面向分布式服务架构的轻量级流量控制产品,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来帮助您保护服务的稳定性。本身在阿里内部已经被大规模采用,比如双11高流量场景,非常稳定。
比如:我们可以通过Sentinel,为秒杀、抢购、抢票、拉票等功能提供API接口层面的流量限制,让突然暴涨而来的用户访问受到统一的管控,使用合理的流量放行规则使得用户都能正常得到服务。同时可以解决应用雪崩效应引发的一系列问题。
三者对比:
Sentinel 是面向分布式服务架构的轻量级流量控制产品,是高可用防护组件,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来帮助您保护服务的稳定性。
流量控制在网络传输中是一个常用的概念,它用于调整网络包的发送数据。因为任意时间到来的请求往往是随机不可控的,而系统的处理能力是有限的。我们需要根据系统的处理能力对流量进行控制。Sentinel 作为一个调配器,可以根据需要把随机的请求调整成合适的形状,如下图所示:
除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。一个服务常常会调用别的模块,可能是另外的一个远程服务、数据库,或者第三方 API 等。例如,支付的时候,可能需要远程调用银联提供的 API;查询某个商品的价格,可能需要进行数据库查询。然而,这个被依赖服务的稳定性是不能保证的。如果依赖的服务出现了不稳定的情况,请求的响应时间变长,那么调用服务的方法的响应时间也会变长,线程会产生堆积,最终可能耗尽业务自身的线程池,服务本身也变得不可用。
因此我们需要对不稳定的弱依赖服务调用进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。
Sentinel采取了两种手段:
方式1:通过并发线程数进行限制:
Sentinel 通过限制资源并发线程的数量,来减少不稳定资源对其它资源的影响。当某个资源出现不稳定的情况下,例如响应时间变长,对资源的直接影响就是会造成线程数的逐步堆积。当线程数在特定资源上堆积到一定的数量之后,对该资源的新请求就会被拒绝。堆积的线程完成任务后才开始继续接收请求。
方式2:通过响应时间对资源进行降级
除了对并发线程数进行控制以外,Sentinel 还可以通过响应时间来快速降级不稳定的资源。当依赖的资源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,直到过了指定的时间窗口之后才重新恢复。
Sentinel 同时对系统的维度提供保护。防止雪崩,是系统防护中重要的一环。当系统负载较高的时候,如果还持续让请求进入,可能会导致系统崩溃,无法响应。在集群环境下,网络负载均衡会把本应这台机器承载的流量转发到其它的机器上去。如果这个时候其它的机器也处在一个边缘状态的时候,这个增加的流量就会导致这台机器也崩溃,最后导致整个集群不可用。
针对这个情况,Sentinel 提供了对应的保护机制,让系统的入口流量和系统的负载达到一个平衡,保证系统在能力范围之内处理最多的请求。
丰富的应用场景:
Sentinel承接了阿里巴巴多年的双十一大促高流量的核心场景,例如秒杀,消息削峰填谷,实时熔断下游不可用应用等.
完备的实时监控:
Sentinel同时提供实时的监控功能,可以在控制台看到接入应用的单台机器秒级数据,甚至500台以下规模的集群的汇总运行情况。
广泛的开源生态:
Sentinel提供开箱即用的与其它开源框架的整合模块,例如与Spring Cloud,Dubbo,gRPC的整合。只需要引入相应的依赖并进行简单的配置即可快速地接入Sentinel。
完善的SPI扩展点:
Sentinel提供简单易用,完善的SPI扩展点。可以通过实现扩展点,快速地定制逻辑。例如定制规则管理,适配数据源等。
资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块。
只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。
围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。
核心库(Java客户端):不依赖任何框架/库,能够运行于所有Java运行环境中,同时对SpringCloud/Dubbo等框架也有较好的支持
控制台(Dashboard):基于Spring Boot开发,打包后可以直接运行,不需要额外的Tomcat等应用容器。
地址: https://github.com/alibaba/Sentinel/releases/tag/v1.8.0
放入指定目录:比如java项目的工作空间。
方式1:
默认端口号是8080
java -jar D:/idea_workspace/sentinel-dashboard-1.8.0.jar
方式2:
可以自己设置端口号
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080-Dproject.name=sentinel-dashboard -Dcsp.sentinel.api.port=8719 -jar D:/idea_workspace/sentinel-dashboard-1.8.0.jar
http://localhost:8080
默认用户名和密码都是sentinel
此时没有关联的微服务
在需要限流的上游服务(调用方)中加入jar包
这里在案例Users服务中添加
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
重启服务Users
此时刷新Dashboard,看不到服务信息。这是因为默认情况下Sentinel 会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包。也就是Sentinel设置了懒加载,解决方法有两种:
方法1:先运行一下Users服务
方法2:配置spring.cloud.sentinel.eager=true ,取消Sentinel控制台懒加载。
再次刷新,可以看到:
我们先简单测试一下Sentinel的流控功能,在设置之前,可以任意刷新Users服务中接口次数。
假设这里设置Users服务下的goods接口1秒钟内只能刷新两次:
再次刷新Users服务中的goods接口:
当QPS超过2次以后,会出现被限流的提示: