SpringCloud Alibaba Sentinel 分布式系统的流量防未兵
一、服务雪崩
如果启动的下单服务不可用,就会出现线程池里所有线程都因等待响应而被阻塞,从而造成整个服务链路不可用,进而导致整个系统的服务雪崩。如图所示:
二、服务雪崩效应
服务雪崩效应:因服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大的过程,就就做雪崩效应。
三、导致服务不可用的原因
3.1、激增流量
- 激增流量导致系统CPU/Load飙高,无法正常处理请求
- 激增流量打垮冷系统(数据库连接未创建、缓存未预热)
- 消息投递速度过快,导致消息处理积压
3.2、不稳定的服务依赖
- 慢sql查询卡爆连接池
- 第三方服务不响应,卡慢线程池
- 业务调用持续出现异常,产生大量的副作用
四、解决方案
4.1、超时机制
- 在不做任何处理的情况下,服务提供者不可用会导致消费者请求线程强制等待,而造成系统资源耗尽。加入超时机制,一旦超时,就释放资源。由于释放资源速度较快,一定程度抑制资源耗尽。
相比之前我们请求积分服务,挂掉的积分服务迟迟得不到响应,加入超时机制后,释放资源速度是快了,如果在2秒之内,并发量还是很大的话,还是有可能挤爆我们的线程池。所以引入服务限流机制
4.2、服务限流
每秒的qps,每秒qps为200,大于200的就等待
4.3、服务熔断
远程服务不稳定或网络抖动时暂时关闭,就叫服务熔断。
- 现实世界的断路器大家肯定都很了解,断路器实时监控电路的情况,如果发现电路电流异常,就会跳闸,从而防止电路被烧毁。
- 软件世界的断路器可以这样理解:实时监测应用,如果发现在一定时间内失败次数 / 失败率 达到一定阈值,就跳闸,断路器打开,此时请求直接返回,而不去调用原本调用的逻辑,跳闸一段时间后(例如10秒),断路器会进入半开状态,这是一个瞬间态,此时允许一次请求,调用该调用的逻辑,如果成功,则断路器关闭,应用正常调用,如果调用依然不成功,断路器继续回到打开状态,过段时间再进入半开状态,通过跳闸,应用可以保护自己,而且避免浪费资源;而通过半开的设计,可实现应用的“自我修复”。
- 所以,同样的道理,当依赖的服务有大量超时时,在让新的请求去访问根本没有意义,只会无畏的消耗现有资源。比如我们设置了超时时间为1秒,如果短时间内有大量请求在1秒内都得不响应,就意味着这个服务出现了异常,此时就没有必要再让其他的请求去访问这个依赖了,这个时候就应该使用断路器避免资源浪费。
4.4、服务降级
- 有服务熔断,必然要有服务降级
- 所谓降级,就是当某个服务熔断之后,服务将不再被调用,此时客户端可以自己准备一个本地fallback(回退)回调,返回一个缺省值,例如:(备用接口/缓存/mock数据)。这样做,虽然服务水平下降,但好歹可用,比直接挂掉要强,当然这也要看适合的业务场景。
四、SpringCloud alibaba Sentinel概述
sentinel是阿里巴巴开源、面向分布式服务架构的高可用防护组件
随着微服务的流行,服务和服务之间我的稳定性变得越来越重要,sentinel是面向分布式服务架构的流量控制组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、从热点防护等多个维度来帮助开发者保障微服务的稳定性。
官网 :https://github.com/alibaba/Sentinel
中文文档 :https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D
五、SpringCloud alibaba Sentinel 控制台
5.1、下载 Sentinel
下载地址 :Releases · alibaba/Sentinel · GitHub
前提确保有 Java 8 的环境,且 8080 端口没有被占用
5.2、进入存放 Sentinel 的目录,并运行命令
java -jar sentinel-dashboard-1.8.0.jar
新建bat文件、批处理启动方式
java -Dserver.port=8858 -Dsentinel.dashboard.auth.username=liuyaofu -Dsentinel.dashboard.auth.password=0407 -jar E:\tools\sentinel-dashboard-1.8.3\sentinel-dashboard-1.8.3.jar
5.3、访问 :http://localhost:8080
5.4、登录账号密码均为 :sentinel
启动之后控制台空空如也,这是因为没有服务与之关联,没启动服务
六、工程环境与sentinel集成
1、新建模块 :alibaba-sentinel-service-8401
2、pom添加依赖
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
3、application.yml
server:#端口号port: 8401spring:application:#服务提供者8401的微服务项目名称name: cloudalibaba-sentinel-servicecloud:#sentinel熔断限流、服务监控sentinel:transport:dashboard: localhost:8858port: 8719 #默认8719,假如被占用了会自动从8719开始依次+1扫描。直至找到未被占用的端口management:endpoints:web:exposure:include: '*'
4、编写主启动类
/*** @Author 刘耀福* @create 2022/1/15 11:01*/
@SpringBootApplication
public class SentinelSerMain8401 {public static void main(String[] args) {SpringApplication.run(SentinelSerMain8401.class, args);}
}
5、Controller
@RestController
public class FlowLimitController {@GetMapping("/testA")public String testA() {return "------testA";}@GetMapping("/testB")public String testB() {return "------testB";}
}
6、启动 alibaba-sentinel-service-8401 项目
10、查看 Sentinel 控制台
因为 Sentinel 采用的是懒加载,执行一下如下请求,重新刷新Sentinel控制台查看
http://localhost:8401/testA
http://localhost:8401/testB
6.1、实时监控
监控接口的通过的QBS和拒绝的QBS
6.2、簇点链路
用来微服务所监控的API
6.3、流控规则介绍
流量控制:(flow control),其原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制, 以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性,RT(响应时间) 1/0.2s =5
资源名:唯一名称,默认请求路径
针对来源:sentinel可以针对调用者进行限流,填写微服务名,默认default (不区分来源)
阈值类型:有QPS何线程数两种
- QPS :表示每秒钟的请求数量,当调用该 api 的 QPS 达到阈值的时候,进行限流。每秒请求数,就是说服务器在一秒的时间内处理了多少个请求
- 线程数 : 当调用该 api 的线程数达到阈值的时候,进行限流
单机阈值:数值1、表示每秒允许一个请求
流控模式:有如下三种模式、直接、关联、链路
- 直接 : api 达到限流条件时,直接限流
- 关联 : 当关联的资源达到阈值时,就限流自己
- 链路 : 只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流)【api级别的针对来源】
流控效果:有快速失败、Warm Up、排队等待
- 快速失败 : 直接失败,抛异常
- Warm Up : 根据codeFactor(冷加载因子,默认3)的值,从阈值codeFactor,经过预热时长,才达到设置的QPS阈值
- 排队等待 : 匀速排队,让请求以匀速的速度通过,阈值类型必须设置为QPS,否则无效
6.4、流控模式演示
6.4.1、 直接(QPS)
1、为 /testA 请求设置流控规则
java代码controller
/*** @Author 刘耀福* @create 2022/1/15 11:02*/
@RestController
public class FlowLimitController {@GetMapping("/flow")@SentinelResource(value ="flow",blockHandler = "flowBlockHandler")public String flow() throws InterruptedException{return "------流控-正常访问";}public String flowBlockHandler(BlockException e) {return "------流控-限流了";}
}
2、查看流控规则
3、发出请求,体验限流
先是一秒点一次,可以正常访问
连续点几次,出现限流了
6.4.2、 直接(线程数)
1、修改上面建的规则
2、java代码Controller
//流控线程数//流控QBS@GetMapping("/flowThread")@SentinelResource(value ="flowThread",blockHandler = "flowThreadBlockHandler")public String flowThread() throws InterruptedException{Thread.sleep(5000);return "------流控-线程数-正常访问";}public String flowThreadBlockHandler(BlockException e) {return "------流控-线程数-限流了";}
3、使用两个浏览器测试,第一个浏览器访问
4、第二个浏览器去请求就被限流了
上面有流控之后都是每个方法配置一个限流方法,这样代码很多、如何做成全局我的限流自定义规则?
使用全局的配置、需要注释掉controller
//@SentinelResource(value ="flow",blockHandler = "flowBlockHandler")
package com.lyf.springcloud.exception;
import com.alibaba.csp.sentinel.adapter.servlet.callback.UrlBlockHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@Component
public class ContentUrlBlockHandler implements UrlBlockHandler {@Overridepublic void blocked(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws IOException {ResultEntity sentinelErrorMsg = null;// 根据异常类型区分违反哪种规则if(e instanceof FlowException){// 限流异常sentinelErrorMsg = ResultEntity.builder().code(100).msg("被限流规则阻挡").build();}else if(e instanceof DegradeException){ // 降级异常sentinelErrorMsg = ResultEntity.builder().code(101).msg("被降级规则阻挡").build();}else if(e instanceof ParamFlowException){ // 热点参数异常sentinelErrorMsg = ResultEntity.builder().code(102).msg("被热点参数规则阻挡").build();}else if(e instanceof SystemBlockException){ // 系统规则异常sentinelErrorMsg = ResultEntity.builder().code(103).msg("被系统规则阻挡").build();}else if(e instanceof AuthorityException){ // 认证异常sentinelErrorMsg = ResultEntity.builder().code(104).msg("被授权规则阻挡").build();}else{sentinelErrorMsg = ResultEntity.builder().code(999).msg("Unknown").build();}httpServletResponse.setStatus(500);httpServletResponse.setCharacterEncoding("utf-8");httpServletResponse.setHeader("Content-Type","application/json;charset=utf-8");httpServletResponse.setContentType("application/json;charset=utf-8");new ObjectMapper().writeValue(httpServletResponse.getWriter(),sentinelErrorMsg);}
}
package com.lyf.springcloud.exception;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;/*** http请求返回的最外层对象*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ResultEntity<T> {/*** 错误码*/private Integer code;/*** 提示信息*/private String msg;/*** 具体内容*/private T data;public static ResultEntity success(Object data){ResultEntity resultEntity = new ResultEntity();resultEntity.setCode(0);resultEntity.setData(data);resultEntity.setMsg("OK");return resultEntity;}public static ResultEntity fail(Integer code,String msg){ResultEntity resultEntity = new ResultEntity();resultEntity.setCode(code);resultEntity.setMsg(msg);return resultEntity;}}
如上,全局异常起作用了
6.4.3 、关联
实际场景 :对于同级别的服务,比如 下单、支付 两个服务,当 支付 流量过高,撑不住了,就限制一下 下单 服务,把资源留给 支付 服务,先撑过去。
1、修改上面建立的流控规则
2、使用 PostMan 发出请求,体验限流
3、post大量请求、接着访问 /testA
6.4.3、链路
根据调用链路入口限流
下面中记录了资源之间的调用链路,这些资源通过调用关系,相互之间构成一棵调用树。这棵树的根节点是一个名字为 getUser 的虚拟节点,调用链的入口都是这个虚节点的子节点。
一棵典型的调用树如下图所示:
getUser/ \/ \/order/test1 /order/test2
上图中来自入口 /order/test1 和 /order/test2的请求都调用到了资源 getUser,Sentinel 允许只根据某个入口的统计信息对 资源限流。
1、修改上面建立的流控规则
2、java代码
test1和test2都调用的getUser()
@Autowiredprivate IOrderService orderService;//关联@GetMapping("/test1")public String test1() {return orderService.getUser();}//关联@GetMapping("/test2")public String test2() {return orderService.getUser();}
/*** @Author 刘耀福* @create 2022/1/20 23:16*/
@Service
public class OrderServiceImpl implements IOrderService {@Override@SentinelResource("getUser")public String getUser() {return "查询用户";}
}
3、浏览器访问 /test2 、/test2
测试会发现链路规则不生效
注意:高版本此功能直接使用不生效,如何解决? 从1.6.3 版本开始,Sentinel Web filter默认收敛所有URL的入口context,因此链路限流不生效。 1.7.0 版本开始(对应SCA的2.1.1.RELEASE),官方在CommonFilter 引入了 WEB_CONTEXT_UNIFY 参数,用于控制是否收敛context。将其配置为 false 即可根据不同的URL 进行链路限流。 SCA 2.1.1.RELEASE之后的版本,可以通过配置spring.cloud.sentinel.web-context-unify=false即可关闭收敛
配置:web-context-unify: false #流控关联不生效配置
测试,此场景拦截不到BlockException,对应@SentinelResource指定的资源必须在@SentinelResource注解中指定 blockHandler处理BlockException
访问test2会被流控、test1不会流控
6.5、流控效果演示
6.5.1、 快速失败(默认的)
就是上面一直出现的提示界面
快速失败方式是默认的流量控制方式,当QPS超过任意规则的阈值后,新的请求就会被立即拒绝,拒绝方式为抛出FlowException。这种方式适用于对系统处理能力确切已知的情况下,比如通过压测确定了系统 的准确水位时。
6.5.2、Warm Up(使用场景为:激增流量)
Warm Up方式,即预热 / 冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。
冷加载因子: codeFactor 默认是3,即请求 QPS 从 threshold / 3 开始,经预热时长逐渐升至设定的 QPS 阈值。
比如:设置的阈值为10,预热时长为5,前1秒内接受3个请求、前2秒内接受5个请求、前3秒内接受7个请求,前5秒内接受10个请求,慢慢的容量达到10,解决了激增流量的问题
6.5.3、排队等待
匀速排队方式会严格控制请求通过的间隔时间,也即是让请 求以均匀的速度通过,对应的是漏桶算
比如我们设置的阈值为10个,超时时间为5秒,现在有20个请求进来了,我们只能接受10个请求,还有10个请求不会直接拒绝,会让他等待5秒
七、熔断降级规则
除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。我们需要对不稳定 的弱依赖服务调用进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。熔断降级作为保护自身 的手段,通常在客户端(调用端)进行配置。流控通常在服务端配置。
弱依赖的服务:就算挂了、也不会给我们的服务造成严重的影像,可以后续补偿
7.1、慢调用比例
慢调用比例 :选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间), 请求的响应时间大于该值则统计为慢调用。当单位统计时长内请求数目大于设置的最小请求数目,并 且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态 ,若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会 再次被熔断。
比如请求一个接口,它的响应时间超过了我设置的响应时间RT,并求5次里面有一次
1、java代码
7.2、异常比例、异常数
以下配置,请求最少两次,到第三次进行熔断、等待10秒之后重新访问,进入异常,再去访问、进行熔断
八、热点规则
什么是热点?比如商品id为1就是热点流量,为2就不是热点流量
注意:
- 1. 热点规则需要使用@SentinelResource("resourceName")注解,否则不生效
- 2. 参数必须是7种基本数据类型才会生效
注意: 资源名必须是@SentinelResource(value="资源名")中 配置的资源名,热点规则依赖于注解
然后在进行编辑、设置热点流量
java代码:
测试热点流量
普通线程数设置的10,到11个请求是会被流控
热点线程数设置的2,到第3个请求会被流控
九、系统规则
SpringCloud Alibaba Sentinel 分布式系统的流量防未兵相关推荐
- 介绍 spring Alibaba Sentinel: 分布式系统的流量防卫兵
目录 一.Sentinel 是什么? 二.Sentinel 具有特征 三.下载和安装 一.Sentinel 是什么? Sentinel 是分布式系统的流量防卫兵,Sentinel 以流量为切入点,从流 ...
- Sentinel 分布式系统的流量防卫兵
sentinel sentinel base 服务编写 关键名词解释 sentinel base 官网: https://github.com/alibaba/Sentinel https://git ...
- SpringCloud(十二)SpringCloudAlibaba Sentinel 分布式系统的流量防卫兵
文章目录 一.Sentinel是什么? 1.1 Sentinel 具有 以下特性 二.Sentinel 使用 2.1 Sentinel 安装. 2.2 创建 `sgg-alibaba-sentinel ...
- Sentinel: 分布式系统的流量防卫兵 1
Sentinel 是什么? 随着微服务的流行,服务和服务之间的稳定性变得越来越重要.Sentinel 以流量为切入点,从流量控制.熔断降级.系统负载保护等多个维度保护服务的稳定性. Sentinel ...
- Sentinel: 分布式系统的流量防卫兵
前言 在 Spring Cloud 体系中,熔断降级我们会使用 Hystrix 框架,限流通常会在 Zuul 中进行处理,Zuul 中没有自带限流的功能,我们可以自己做限流或者集成第三方开源的限流框架 ...
- sentinel分布式系统的流量防卫兵
首先在根目录下开启cmd黑窗口启用jar文件 java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproj ...
- 分布式系统的流量防卫兵Sentinel-入门指南
1.介绍 欢迎来到 Sentinel 的世界!这篇新手指南将指引您快速入门 Sentinel. Sentinel: 分布式系统的流量防卫兵 1.1 Sentinel 是什么? 随着微服务的流行,服务和 ...
- 3 - 分布式系统的流量防卫兵:Sentinel
Java工程师的进阶之旅 学习 SpringCloud2 这一篇就够了 1 - SpringCloud Alibaba 介绍 2 - 服务注册与配置中心:Nacos 3 - 分布式系统的流量防卫兵:S ...
- SpringCloud Alibaba Sentinel 流量控制规则介绍与配置
概述:流量控制(flow control),其原理是sentinel断路器通过监控应用服务调用的QPS或调用并发线程数来实现调用控制.当QPS或线程数达到配置的阈值时,进行响应的服务降级功能,从而到达 ...
最新文章
- 计算机要学打字吗,有了电脑打字,还需要练字吗?
- Zookeeper_环境搭建及客户端使用
- 无线路由器参数设置精通技巧
- android java加密_Android Java字符串加密
- Qt文档阅读笔记-共享库的创建与调用
- Mr.J--JavaScript-恶搞小代码
- python 文件和目录基本操作_Python常用的文件及文件路径、目录操作方法汇总介绍...
- 力控数据写入mysQL_绝对干货,教你4分钟插入1000万条数据到mysql数据库表,快快进来...
- 二叉树遍历结果推二叉树_二叉树遍历(PreOrder,InOrder,PostOrder)
- 关于js中this指向的总结
- c语言从入门到精通的几个阶段
- 淘宝买家和卖家的经典对话
- python实现爬取12306所有站点及其编码信息(附源代码)!
- ANdroid8.0以上创建快捷方式
- FPGA2016~2018,FPL2017会议论文整理(持续更新)
- 喜欢吃鱼的朋友一定要转哦
- android开源日志库的使用
- 论文研读——n个物体相互间的碰撞避免
- 4、关于step的设置
- 六方ZnS包裹碳纳米管复合粉体/PbS纳米晶原位包裹碳纳米管的复合材料/壳聚糖包裹的多壁碳纳米管