微服务保护

一、初识 Sentinel

1. 雪崩问题及解决方案

微服务调用链路中的某个服务故障

引起整个链路中的所有微服务都不

可用,这就是雪崩

   常见解决方式有四种:

超时处理:设定超时时间,请求

    过一定时间没有响应就返回错误信

    息,不会无休止等待

舱壁模式限定每个业务能使用的

    线程数,避免耗尽整个 tomcat 的资

    源,因此也叫线程隔离

熔断降级:由断路器统计业务执行

    的异常比例,如果超出阈值则会熔断

    该业务,拦截访问该业务的一切请求

流量控制:限制业务访问的 QPS,

    避免服务因流量的突增而故障

2. 服务保护技术对比

3. Sentinel 介绍和安装

Sentinel 是阿里巴巴开源的一款微服务

流量控制组件

https://sentinelguard.io/zh-cn/index.html Sentinel

具有以下特征:

① 丰富的应用场景

② 完备的实时监控

③ 广泛的开源生态

④ 完善的 SPI 扩展点

(2) 安装 Sentinel 控制台:  

① 准备好 sentinel-dashboard-1.8.1.jar

② 执行 java -jar sentinel-dashboard-1.8.1.jar

③ 访问:localhost:8080 即可看到控制台页面,

    默认的账户和密码都是 sentinel

(3) 修改 Sentinel 的默认端口、账户、密码

java -jar sentinel-dashboard-1.8.1.jar -Dserver.port=8080

4. 微服务整合 Sentinel

在 order-service 中整合 Sentinel,并且连接

Sentinel 的控制台,步骤如下:

(1) 引入 sentinel 依赖:

<!--sentinel-->
<dependency><groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

(2) 配置控制台地址

修改 application.yaml 文件,添加下面内容:

server:port: 8088
spring:cloud: sentinel:transport:dashboard: localhost:8080

(3) 访问微服务的任意端点,触发 sentinel 监控

访问 http://localhost:8088/order/101

二、限流规则

1. 快速入门

簇点链路:就是项目内的调用链路,链路

                 中被监控的每个接口就是一个

                 资源

默认 sentinel 会监控 SpringMVC 的每一

个端点 (Endpoint),因此 SpringMVC 的

每一个端点 (Endpoint) 就是调用链路中的

一个资源。流控、熔断等都是针对簇点链

路中的资源来设置的,因此我们可以点击

对应资源后面的按钮来设置规则

点击资源 /order/{orderId} 后面的流控

按钮,就可以弹出表单,表单中可以

添加流控规则

图中含义:限制 /order/{orderId} 这个资源

的单机 QPS 为 1,即每秒只允许1次请求

超出的请求会被拦截并报错

2. 流控模式

在添加限流规则时,点击高级选项,可以选

择三种流控模式:

直接:统计当前资源的请求,触发阈

    值时对当前资源直接限流,也是默认

    的模式

关联:统计与当前资源相关的另一个

    资源,触发阈值时,对当前资源限流

链路:统计从指定链路访问到本资源

    的请求,触发阈值时,对指定链路限

    流

(2) 关联

满足下面条件可以使用关联模式:

① 两个有竞争关系的资源

② 一个优先级较高,一个优先级较低

当 /write 资源访问量触发阈值时,就会对

/read 资源限流,避免影响 /write 资源 

(3) 链路

例如有两条请求链路:

/test1 → /common

/test2 → /common

如果只希望统计从 /test2 进入到 /common

的请求,则可以这样配置 

① Sentinel 默认只标记 Controller 中的方

    法为资源,如果要标记其他方法,需要

    利用 @SentineResource 注解

@SentineResource("goods")
public void queryGoods() {System.err.println("查询商品");
} 

② Sentinel 默认会将 Controller 方法做

    context 整合,导致链路模式的流控失

    效

   需要修改 application.yml,添加配置:  

spring:cloud:sentinel:web-context-unify:false # 关闭 context 整合 

3. 流控效果

流控效果是指请求达到流控阈值时应该

采取的措施

  包括三种:

快速失败:达到阈值后,新的请求会被

    立即拒绝并抛出 FlowException 异常

    (默认)

warm up预热模式,对超出阈值的请

    求同样是拒绝并抛出异常,但这种模式

    阈值会动态变化,从一个较小值逐渐增

    加到最大阈值

排队等待:让所有的请求按照先后次序

    排队执行,两个请求的间隔不能小于指

    定时长

4. 热点参数限流

之前的限流是统计访问某个资源的所有请求

判断是否超过 QPS 阈值,而热点参数限流

分别统计参数值相同的请求,判断是否超

过 QPS 阈值

(1) 配置示例: 

对 hot 这个资源的 0 号参数 (第一个参数)

做统计,每 1 秒相同参数值的请求数不能

超过 5

 

(2) 在高级选项中,可以对部分参数设置

     例外配置:

结合上一个配置,这里的含义是对 0 号

的 long 类型参数限流,每 1 秒相同参数

的 QPS 不能超过 5

有两个例外:

① 如果参数值是 100,则每 1 秒允许的

    QPS 为 10

② 如果参数值是 101,则每 1 秒允许的

    QPS为 15 

注意:热点参数限流对默认的 SpringMVC

          资源无效

三、隔离和降级

虽然限流可以尽量避免因高并发而引起的

服务故障,但服务还会因为其它原因而故

障,而要将这些故障控制在一定范围,避

免雪崩,就要靠线程隔离 (舱壁模式) 和熔

断降级手段了,不管是线程隔离还是熔断

降级,都是对客户端 (调用方) 的保护

1. FeignClient 整合 Sentinel

(1) 修改 OrderService 的 application.yml 文件,

     开启 Feign 的 Sentinel 功能

feign:sentinel:enabled: true # 开启Feign的Sentinel功能

(2) 给 FeignClient 编写失败后的降级逻辑

方式一:FallbackClass无法对远程调用

              的异常做处理

方式二:FallbackFactory,可以对远程调

              用的异常做处理,我们选择这种

  给 FeignClient 编写 FallbackFactory 并注册

  为 Bean 

@Slf4j
@Bean
public class UserClientFallbackFactory implements FallbackFactory<UserClient> {@Overridepublic UserClient create(Throwable throwable) {// 创建UserClient接口实现类,实现其中的方法,编写失败降级的处理逻辑return new UserClient() {@Overridepublic User findById(Long id) {// 记录异常信息log.error("查询用户失败", throwable);// 根据业务需求返回默认的数据,这里是空用户return new User();}};}
}

(3) 在 feing-api 项目中的 UserClient 接口中

    使用 UserClientFallbackFactory

@FeignClient(value = "userservice", fallbackFactory = UserClientFallbackFactory.class)
public interface UserClient {@GetMapping("/user/{id}")User findById(@PathVariable("id") Long id);
}

2. 线程隔离(舱壁模式)

   线程隔离有两种方式实现:

① 线程池隔离

② 信号量隔离 (Sentinel 默认采用)

(1) 信号量隔离

优点:轻量级,无额外开销

缺点:不支持主动超时

           不支持异步调用

场景:高频调用,高扇出

(2) 线程池隔离

优点:支持主动超时

           支持异步调用

缺点:线程的额外开销比较大

场景:低扇出

低扇出:就是说让一个类里少量或适中地

              使用其他的类

高扇出 (超过约7个):说明一个类使用了大

         量其他的类,因为可能变得过于复杂

 在添加限流规则时,可以选择两种阈值类型:

QPS:就是每秒的请求数

线程数:是该资源能使用用的 tomcat 线程

             数的最大值,也就是通过限制线程

             数量,实现舱壁模式 

3. 熔断降级

熔断降级是解决雪崩问题的重要手段,其

思路是由断路器统计服务调用的异常比例、

慢请求比例,如果超出阈值则会熔断该服

务。

即拦截访问该服务的一切请求;而当服务

恢复时,断路器会放行访问该服务的请求

断路器熔断策略有三种:

① 慢调用

② 异常比例

③ 异常数

(1) 慢调用

业务的响应时长 (RT) 大于指定时长的请

求,统计单位时长内慢调用的比例,超

过阈值则熔断

RT 超过 500ms 的调用是慢调用,统计最近

10000ms 内的请求,如果请求量超过 10 次,

并且慢调用比例不低于0.5,则触发熔断,熔

断时长为5秒,然后进入 half-open 状态,放

行一次请求做测试

(2) 异常比例

统计单位时长内异常调用的比例,超过

阈值则熔

 

统计最近 1000ms 内的请求,如果请求量

超过 10 次,并且异常比例不低于 0.5,则

触发熔断,熔断时长为 5 秒,然后进入

half-open 状态,放行一次请求做测试 

(3) 异常数

统计单位时长内异常调用的次数,超过

阈值则熔断

 

 

四、授权规则

(1) 授权规则

授权规则可以对调用方的来源做控制,

有两种方式:

白名单:来源 (origin) 在白名单内的调用者

              允许访问

黑名单:来源 (origin) 在黑名单内的调用者

              不允许访问

例如,我们限定只允许从网关来的请求访问

orde-service,那么流控应用中就填写网关

的名称

① Sentinel 是通过 RequestOriginParser

    这个接口的 parseOrigin 来获取请求的

    来源的

public interface RequestOriginParser {/*** 从请求request对象中获取origin,获取方式自定义*/String parseOrigin(HttpServletRequest request);
}

在 Sentinel 中,该接口的 parseOrigin 方法

返回的永远是 default,也就是说,无论请求

开源是来自网关还是浏览器,Sentinel 根本

无法区分这两个请求

需要实现这个接口,编写它的业务逻辑,让

从网关来的请求和浏览器来的请求返回不同

的结果

② 从 request 中获取一个名为 origin 的请求

    头,作为 origin 的值

@Component
public class HeaderOriginParser implements RequestOriginParser {@Overridepublic String parseOrigin(HttpServletRequest httpServletRequest) {// 尝试获取请求头String origin = httpServletRequest.getHeader("origin");// 非空判断if (StringUtils.isEmpty(origin)){origin = "blank";}return origin;}
}

③ 在 gateway 服务中,利用网关的全局过

    滤器添加名为 gateway 的 origin 头

spring:cloud:gateway:default-filters:- AddRequestHeader=origin,gateway # 添加名为origin的请求头,值为gateway

④ 给 /order/{orderId} 配置授权规则:

(2) 自定义异常结果

默认情况下,发生限流、降级、授权拦截

时,都会抛出异常到调用方

如果要自定义异常时的返回结果,需要实现

BlockExceptionHandler 接口:

public interface BlockExceptionHandler {// 处理请求被限流、降级、授权拦截时抛出的异常void handle(HttpServletRequest var1, HttpServletResponse var2, BlockException var3) throws Exception;
}

BlockException 包含很多个子类,以应对不同

的场景:

异常说明
FlowException限流异常
ParamFlowException热点参数限流的异常
DegradeException降级异常
AuthorityException授权规则异常
SystemBlockException系统规则异常

在 order-service 中定义类,实现 BlockExceptionHandler 接口:

@Component
public class SentinelExceptionHandler implements BlockExceptionHandler {@Overridepublic void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {String msg = "未知异常";int status = 429;if (e instanceof FlowException){msg = "请求被限流了";} else if (e instanceof ParamFlowException){msg = "请求被热点参数限流了";} else if (e instanceof DegradeException){msg = "请求被降级了";} else if (e instanceof AuthorityException) {msg = "没有权限访问";status = 401;}httpServletResponse.setContentType("application/json;charset=utf-8");httpServletResponse.setStatus(status);httpServletResponse.getWriter().write("{\"msg\": " + msg + ", \"status\":" + status + "}");}
}

五、规则持久化

1. 规则管理模式

Sentinel 的控制台规则管理有三种模式:

① 原始模式:控制台配置的规则直接推送到

  Sentinel 客户端,也就是我们的应用,然后

  保存在内存中,服务重启则丢失

 

② pull 模式:控制台将配置的规则推送到

  Sentinel 客户端,而客户端会将配置规则

  存在本地文件或数据库中,以后会定时去本

  地文件或数据库中查询,更新本地规则

③ push 模式:控制台将配置规则推送到远程

   配置中心,例如 Nacos 或 Zookeeper,

   Sentinel 客户端监听 Nocas,获取配置变更

   的推送消息,完成本地配置更新 (推荐)

2. 实现push模式

push 模式的实现最为复杂,因为其依赖于

nacos,并且需要改 Sentinel 控制台的源码,

整体步骤如下:

(1) 修改 order-service 服务,使其监听

     Nacos 配置中心

① 引入依赖

<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

② 配置 nacos 地址

spring:cloud:sentinel:datasource:flow:nacos:server-addr: localhost:8848 # nacos地址dataId: orderservice-flow-rulesgroupId: SENTINEL_GROUPrule-type: flow   # 还可以是degrade、authority、param-flowdegrade:nacos:server-addr: localhost:8848 # nacos地址dataId: orderservice-degrade-rulesgroupId: SENTINEL_GROUPrule-type: degrade   # 还可以是degrade、authority、param-flow


(2) 修改 Sentinel-dashboard 源码,配置

     nacos 数据源

修改源码的 pom 文件,将 sentinel-

datasource-nacos 依赖的 scope 去掉

<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId><!--<scope>test</scope>-->
</dependency>


(3) 修改 Sentinel-dashboard 源码, 修改前端

     页面

① 拷贝 test 目录下的 nacos 代码到 main下的

   com.alibaba.csp.sentinel.dashboard.rule

② 修改刚刚拷贝的 nacos 包下的 NacosConfig

    类,修改其中的 nacos 地址

@Bean
public ConfigService nacosConfigService() throws Exception {return ConfigFactory.createConfigService("localhost:8848"); 
}

④ 修改 com.alibaba.csp.sentinel.dashboard.

    controller.v2 包下的 FlowControllerV2 类

 

(4) 重新编译、打包 Sentinel-dashboard 源码

① 修改 src/main/webapp/resources/app/scripts/

   directives/sidebar/ 目录下的 sidebar.html 文件,

   将其中的这部分注释打开

② 修改其中的文本

<li ui-sref-active="active" ng-if="entry.appType==0"><a ui-sref="dashboard.flow({app: entry.app})"><i class="glyphicon glyphicon-filter"></i>&nbsp;&nbsp;流控规则-NACOS</a>
</li>

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/26827.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

同步和异步的区别

同步&#xff0c;可以理解为在执行完一个函数或方法之后&#xff0c;一直等待系统返回值或消息&#xff0c;这时程序是处于阻塞的&#xff0c;只有接收到返回的值或消息后才往下执行其他的命令&#xff1b; 异步&#xff0c;执行完函数或方法后&#xff0c;不必阻塞性地等待返回…

每天一道C语言编程练习(5):尼科彻斯定理

题目描述 验证尼科彻斯定理&#xff0c;即&#xff1a;任何一个整数m的立方都可以写成m个连续奇数之和。 输入格式 任一正整数 输出格式 该数的立方分解为一串连续奇数的和 样例输入 13 样例输出 13*13*132197157159161163165167169171173175177179181 代码如下&#…

C++模拟实现unordered_map和unordered_set(哈希)

目录 一、unordered系列关联式容器 1.1 unordered_map 1.1.1 unordered_map 1.1.2 unordered_map接口说明 1. unordered_map的容量 2. unordered_map的迭代器 3.unordered_map的元素访问 4. unordered_map的查询 5. unordered_map的修改操作 6. unordered_map的桶操作…

学习率的选择

学会画图去看学习率是否符合 梯度下降算法收敛所需要的迭代次数根据模型的不同而不同&#xff0c;我们不能提前预知&#xff0c;我们可以绘制迭代次数和代价函数的值的图表来观测算法在何时趋于收敛。 -自动测试方法 也有一些自动测试是否收敛的方法&#xff0c;例如将代价函数…

学无止境·MySQL⑧(Redis)

Redis和Mongodb练习 Redis1、安装redis2、string类型数据的命令操作&#xff1a;设置键值&#xff1a;读取键值数值类型自增1数值类型自减1查看值的长度 3、list类型数据的命令操作对列表city插入元素&#xff1a;Shanghai Suzhou Hangzhou将列表city里的头部的元素移除将name列…

TCR中的缓存和共享属性与PTE中的缓存和共享属性的区别是啥?

那么就请继续思考&#xff1a; Translation Table Walk访问页表的缓存策略&#xff0c;这里的页表到底是缓存到cache中&#xff0c;还是缓存到PTW中呢&#xff1f;

【PostgreSQL内核学习(一)—— Ubuntu源码安装PostgreSQL】

Ubuntu源码安装PostgreSQL 1. PostgreSQL官网下载压缩包2. 解压&安装2.1 解压文件2.2 安装依赖2.3 执行安装2.4 执行安装2.5 添加路径到文件 3. 初始化数据库与使用3.1 初始化数据库3.2 启动数据库服务3.3 启动数据库 1. PostgreSQL官网下载压缩包 下载地址&#xff1a;ht…

数据结构---手撕图解二叉树(含大量递归图解)

文章目录 写在前面二叉树的创建二叉树的遍历前序遍历中序遍历后序遍历层序遍历 二叉树的销毁二叉树节点个数二叉树叶子节点的个数二叉树查找值为x的节点二叉树是否为完全二叉树 写在前面 二叉树的几乎所有实现都是依靠递归实现&#xff0c;递归的核心思路是把任何一个二叉树看…

idea专业版和idea社区版整合Tomcat,并将war包部署

文章目录 idea专业版和idea社区版整合Tomcat&#xff0c;并将war包部署一、idea专业版部署二、idea社区版部署三、错误案例 idea专业版和idea社区版整合Tomcat&#xff0c;并将war包部署 开发过程中&#xff0c;由于需要运用云平台&#xff0c;所以从新配置开发环境&#xff0…

编程导航算法通关村第 1关 | 单链表的操作

编程导航算法通关村第 1关 | 链表的操作 文章目录 编程导航算法通关村第 1关 | 链表的操作单链表链表的定义初始化链表的遍历获取链表的长度链表的插入链表的节点的删除 双向链表节点的定义双向链表的定义节点的打印获取长度头部插入元素尾部插入元素链表的删除 单链表 链表的…

红队打靶:billu_b0x打靶思路详解(vulnhub)

目录 写在开头 第一步&#xff1a;主机发现和端口扫描 第二步&#xff1a;Web渗透 第三步&#xff1a;利用文件包含进行代码审计 第四步&#xff1a;图片马上传与反弹shell 第五步&#xff1a;敏感文件提权 总结与思考 写在开头 我的博客等级终于到三级了&#xff0c;…

部署langchain+chatglm

先参考&#xff1a;window零基础部署langchain-ChatGLM_飞奔的屎壳郎的博客-CSDN博客 安装一部分&#xff0c; 1.GCC安装 gcc64位下载 一定要装64位的gcc&#xff0c;因为我的电脑是w10 64位的&#xff0c;装32位运行langchain报错并配置环境变量 可直接用压缩包中的文件&am…