SpringCloud Alibaba学习笔记 ——(六、Sentinel 服务保护框架)

最后

为什么我不完全主张自学?
平台上的大牛基本上都有很多年的工作经验了,你有没有想过之前行业的门槛是什么样的,现在行业门槛是什么样的?以前企业对于程序员能力要求没有这么高,甚至十多年前你只要会写个“Hello World”,你都可以入门这个行业,所以以前要入门是完全可以入门的。
②现在也有一些优秀的年轻大牛,他们或许也是自学成才,但是他们一定是具备优秀的学习能力,优秀的自我管理能力(时间管理,静心坚持等方面)以及善于发现问题并总结问题。
如果说你认为你的目标十分明确,能做到第②点所说的几个点,以目前的市场来看,你才真正的适合去自学。

除此之外,对于绝大部分人来说,报班一定是最好的一种快速成长的方式。但是有个问题,现在市场上的培训机构质量参差不齐,如果你没有找准一个好的培训班,完全是浪费精力,时间以及金钱,这个需要自己去甄别选择。

我个人建议线上比线下的性价比更高,线下培训价格基本上没2W是下不来的,线上教育现在比较成熟了,此次疫情期间,学生基本上都感受过线上的学习模式。相比线下而言,线上的优势以我的了解主要是以下几个方面:
①价格:线上的价格基本上是线下的一半;
②老师:相对而言线上教育的师资力量比线下更强大也更加丰富,资源更好协调;
③时间:学习时间相对而言更自由,不用裸辞学习,适合边学边工作,降低生活压力;
④课程:从课程内容来说,确实要比线下讲的更加深入。

应该学哪些技术才能达到企业的要求?(下图总结)

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

import java.util.ArrayList;

import java.util.List;

/**

  • @Classname SentinelApplicationRunner

  • @Description 我们将初始化的规则,放在这里加载,这是 Springboot 提供的一个启动加载接口

  • @Date 2021/1/30 14:31

  • @Created by CodingGorit

  • @Version 1.0

*/

@Configuration

public class SentinelApplicationRunner implements ApplicationRunner {

// 定义的限流规则名称

private static final String GETORDER_KEY = “orderToMenber”;

private Logger log = LoggerFactory.getLogger(SentinelApplicationRunner.class);

@Override

public void run(ApplicationArguments args) throws Exception {

List rules = new ArrayList();

FlowRule rule1 = new FlowRule();

rule1.setResource(GETORDER_KEY); // 限流规则名称

//qps 控制在 1 以内

rule1.setCount(1);

//qps 限流

rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);

rule1.setLimitApp(“default”);

rules.add(rule1);

FlowRuleManager.loadRules(rules);

log.info(“>>> 限流配置加载成功”);

}

}

  1. 然后再次启动,就能直接访问 http://localhost:8080/orderToMenber 实现服务限流了

6.3.2 使用注解实现服务限流

/**

  • @SentinelResource 参数主要如下

  • fallback 服务降级执行本地方法

  • blockHandler 限流/熔断 出现异常执行的方法

  • value 指定我们的资源名称

  • @return

*/

@SentinelResource(value = GETORDER_KEY, blockHandler = “getOrderQpsException”)

@RequestMapping(“/orderToMemberSentinelResource”)

public String orderToMemberSentinelResource() {

return “orderToMemberSentinelResource”;

}

/**

  • 被限流后返回的提示

  • @param e

  • @return

*/

public String getOrderQpsException(BlockException e) {

e.printStackTrace();

return “该接口被限流了”;

}

6.3.3 Springboot 整合 Sentinel 仪表盘

  1. 先启动 Sentinel 控制台:

java -Dserver.port=8718 -Dcsp.sentinel.dashboard.server=localhost:8718 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.0.jar

  1. 登录的账号密码:sentinel sentinel

  2. SpringBoot 配置整合 Sentinel 控制台

spring:

application:

name: gorit-order

cloud:

nacos:

discovery:

server-addr: 127.0.0.1:8848

sentinel:

transport:

dashboard: 127.0.0.1:8718

eager: true

  1. 重新启动 SpringBoot

  1. 编写接口

/**

  • 基于控制台实现流量规则限流

  • @return

*/

@RequestMapping(“/getOrderConsole”)

public String getOrderConsole () {

return “getOrderConsole”;

}

/**

  • 如果没有使用 @SentinelResource 注解,默认资源名称为接口路径 /getOrderConsole

*/

  1. 在控制台添加规则

在这里插入图片描述

  1. 被限流返回的结果

Blocked by Sentinel (flow limiting)

  1. 如果要实现和上述一样的返回效果,只需要加上 @SentinelResouce 注解即可

PS:如果配置了注解,就会和默认的资源名称冲突,所以要删除默认的资源名称

6.3.4 实现信号量隔离

限流规则设置 线程数

// 基于信号量, 在控制台设置规则的时候,配置为 线程数

@SentinelResource(value = GETORDER_KEY, blockHandler = “getOrderQpsException”)

@RequestMapping(“/getOrderSemaphore”)

public String getOrderSemaphore () {

log.info(“>>>” + Thread.currentThread().getName());

return “getOrderSemaphore”;

}

阙值改为线程数

在这里插入图片描述

访问效果

在这里插入图片描述

如果看不到效果,可以在代码中加入 Thread.sleep(500) ,使线程阻塞即可

6.4 Sentinel 数据持久化 & 实现服务降级 & 服务熔断


  1. Sentinel 持久化方案

  2. 网关整合 Sentinel 实现限流

  3. 如何对服务实现动态降级

  4. 降级的策略 RT、错误比例、次数

6.4.1 Sentinel 数据持久化的方式(基于 nacos 配置中心实现持久化)

Sentinel 支持数据规则持久化的,官方默认支持 5 种(sentinel-nacos 1.7.0 版本)

  1. nacos 分布式配置中心

  2. 携程阿波罗

  3. 存放本地文件

  4. Zookeeper

  5. redis

一、在 nacos 中创建流控规则


gorit-order-sentinel

在这里插入图片描述

我们可以在 Nacos 编写 Sentinel 的资源配置,然后整合 sentinel-nacos 的配置

[

{

“resource”: “/getOrderSentinel”,

“limitApp”: “default”,

“grade”: 1,

“count”: 1,

“strategy”: 0,

“controlBehavior”: 0,

“clusterMode”: false

}

]

  • resource: 资源名,即限流规则的作用对象

  • limitApp: 流控针对的调用来源,若为 default 则不区分调用来源

  • grade:限流阙值类型(QPS 或并发线程数);0 代表根据并发数量来限流, 1 代表 QPS 来进行流量控制

  • count:限流阙值

  • strategy:调用关系限流策略

二、SpringBoot 客户端 整合 nacos-sentinel


依赖配置

com.alibaba.cloud

spring-cloud-starter-alibaba-sentinel

2.1.0.RELEASE

com.alibaba.csp

sentinel-datasource-nacos

1.7.0

PS:我用的 SpringBoot 版本是 2.3.4 RELEASE,之前用的 nacos-sentinel 的版本是 1.5.6,启动老是报错,好来改成 1.7.0 就出来了

配置文件 (application.yml)

spring:

application:

name: gorit-order

cloud:

nacos:

discovery:

server-addr: 127.0.0.1:8848

sentinel:

transport:

dashboard: 127.0.0.1:8718 # 这个是控制台的地址,因为我启动时,指定了控制台启动的端口为 8718

eager: true

datasource:

  • nacos:

server-addr: localhost:8848 # nacos 连接地址

group-id: DEFAULT_GROUP # nacos 连接分组

rule-type: flow # 路由存储规则 flow、degrade、param-flow、gw-flow

data-id: ${spring.application.name}-sentinel # 读取配置文件的 data-id

data-type: json # 读取配置文件累心为 JSON 和 XML

server:

port: 8091

编写 getOrderSentinel 接口

// 集成 nacos 实现 sentinel 流控规则的持久化

@RequestMapping(“/getOrderSentinel”)

public String getOrderSentinel() {

return “OrderSentinel”;

}

启动项目

三、更新前面 Nacos 的配置


更新前

在这里插入图片描述

更新 nacos 配置

在这里插入图片描述

更改后

看,我们已经实现了通过 nacos 配置中心修改限流规则了

PS: 如果发现重启没有生效的话,是因为我们之前编写的 SentinelApplicationRunner 类会初始化我们的流控配置,所以将其注释掉,就可以解决 nacos 持久化被覆盖的问题

6.4.2 Gateway 整合 sentinel 实现服务限流

官方文档

Gateway 是采用 netty 启动的,不支持 Servlet-API。所以添加了 Springboot-web 的依赖就会报错

网关流控原理

当通过 GatewayRuleManager 加载网关流控规则(GatewayFlowRule)时,无论是否针对请求属性进行限流,Sentinel 底层都会将网关流控规则转化为热点参数规则(ParamFlowRule),存储在 GatewayRuleManager 中,与正常的热点参数规则相隔离。转换时 Sentinel 会根据请求属性配置,为网关流控规则设置参数索引(idx),并同步到生成的热点参数规则中。

外部请求进入 API Gateway 时会经过 Sentinel 实现的 filter,其中会依次进行 路由/API 分组匹配请求属性解析参数组装。Sentinel 会根据配置的网关流控规则来解析请求属性,并依照参数索引顺序组装参数数组,最终传入 SphU.entry(res, args) 中。Sentinel API Gateway Adapter Common 模块向 Slot Chain 中添加了一个 GatewayFlowSlot,专门用来做网关规则的检查。GatewayFlowSlot 会从 GatewayRuleManager 中提取生成的热点参数规则,根据传入的参数依次进行规则检查。若某条规则不针对请求属性,则会在参数最后一个位置置入预设的常量,达到普通流控的效果。

  1. 新建一个 module,并命名为 gorit-gateway

  2. 添加依赖

org.springframework.cloud

spring-cloud-starter-gateway

2.2.4.RELEASE

com.alibaba.csp

sentinel-spring-cloud-gateway-adapter

1.7.0

  1. 编写项目配置依赖 application.yml

spring:

application:

name: gorit-order-gateway-8080

cloud:

nacos:

discovery:

server-addr: 127.0.0.1:8848

gateway:

routes:

  • id: my-member # 这个用不到,是之前写过的,可以直接 copy 过来

uri: lb://gorit-member

匹配规则

predicates:

  • Path=/gorit-member/**

  • id: gorit

uri: https://www.gorit.cn/ # 转发到我的个人网站

匹配规则

predicates:

  • Path=/**

enabled: true

server:

port: 8080

  1. 注入对应的 SentinelGatewayFilter 实例以及 SentinelGatewayBlockExceptionHandler 实例即可

package cn.gorit.config;

import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;

import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;

import org.springframework.beans.factory.ObjectProvider;

import org.springframework.cloud.gateway.filter.GlobalFilter;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.core.Ordered;

import org.springframework.core.annotation.Order;

import org.springframework.http.codec.ServerCodecConfigurer;

import org.springframework.web.reactive.result.view.ViewResolver;

import java.util.Collections;

import java.util.List;

/**

  • @Classname GatewayConfiguration

  • @Description TODO

  • @Date 2021/1/31 22:34

  • @Created by CodingGorit

  • @Version 1.0

*/

@Configuration

public class GatewayConfiguration {

private final List viewResolvers;

private final ServerCodecConfigurer serverCodecConfigurer;

public GatewayConfiguration(ObjectProvider<List> viewResolversProvider,

ServerCodecConfigurer serverCodecConfigurer) {

this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);

this.serverCodecConfigurer = serverCodecConfigurer;

}

@Bean

@Order(Ordered.HIGHEST_PRECEDENCE)

public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {

// Register the block exception handler for Spring Cloud Gateway.

return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);

}

@Bean

@Order(Ordered.HIGHEST_PRECEDENCE)

public GlobalFilter sentinelGatewayFilter() {

return new SentinelGatewayFilter();

}

}

  1. 配置限流的接口(对应上述第一段实现原理)

package cn.gorit.config;

import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;

import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;

import org.springframework.boot.ApplicationArguments;

import org.springframework.boot.ApplicationRunner;

import org.springframework.context.annotation.Configuration;

import java.util.HashSet;

import java.util.Set;

/**

  • @Classname SentinelApplicationRunner

  • @Description TODO

  • @Date 2021/1/31 22:37

  • @Created by CodingGorit

  • @Version 1.0

*/

@Configuration

public class SentinelApplicationRunner implements ApplicationRunner {

@Override

public void run(ApplicationArguments args) throws Exception {

initGatewayRules();

}

/**

  • 配置网关限流规则

*/

private void initGatewayRules() {

Set rules = new HashSet<>();

// 设置规则

rules.add(new GatewayFlowRule(“gorit”)

// 设置阙值

.setCount(1)

// 设置时间窗口,单位是秒,默认是 1 s

.setIntervalSec(1));

GatewayRuleManager.loadRules(rules);

}

}

然后即可实现限流效果

PS:

  1. 如果要实现动态限流,并且持久化,将配置写入 nacos 配置中心即可

  2. 如果要实现自定义限流返回的信息,需要重写该方法:

public class SentinelGatewayBlockExceptionHandler implements WebExceptionHandler

  1. 然后注入我们重写的 handler 即可

*/

public class JsonSentinelGatewayBlockExceptionHandler implements WebExceptionHandler {

public JsonSentinelGatewayBlockExceptionHandler(List viewResolvers) {

}

@Override

public Mono handle(ServerWebExchange exchange, Throwable throwable) {

ServerHttpResponse serverHttpResponse = exchange.getResponse();

serverHttpResponse.getHeaders().add(“Content-Type”,“application/json;charset=utf-8”);

byte[] datas = “{“code”:403,“msg”:“API 接口被限流”}”.getBytes(StandardCharsets.UTF_8);

DataBuffer buffer = serverHttpResponse.bufferFactory().wrap(datas);

return serverHttpResponse.writeWith(Mono.just(buffer));

}

}

6.4.3 实现服务动态降级

官方文档

服务出现异常时,会自动服务降级,禁止外来继续访问,不会执行真正的逻辑

最后

ActiveMQ消息中间件面试专题

  • 什么是ActiveMQ?
  • ActiveMQ服务器宕机怎么办?
  • 丢消息怎么办?
  • 持久化消息非常慢怎么办?
  • 消息的不均匀消费怎么办?
  • 死信队列怎么办?
  • ActiveMQ中的消息重发时间间隔和重发次数吗?

ActiveMQ消息中间件面试专题解析拓展:

BAT面试文档:ActiveMQ+redis+Spring+高并发多线程+JVM


redis面试专题及答案

  • 支持一致性哈希的客户端有哪些?
  • Redis与其他key-value存储有什么不同?
  • Redis的内存占用情况怎么样?
  • 都有哪些办法可以降低Redis的内存使用情况呢?
  • 查看Redis使用情况及状态信息用什么命令?
  • Redis的内存用完了会发生什么?
  • Redis是单线程的,如何提高多核CPU的利用率?

BAT面试文档:ActiveMQ+redis+Spring+高并发多线程+JVM


Spring面试专题及答案

  • 谈谈你对 Spring 的理解
  • Spring 有哪些优点?
  • Spring 中的设计模式
  • 怎样开启注解装配以及常用注解
  • 简单介绍下 Spring bean 的生命周期

Spring面试答案解析拓展

BAT面试文档:ActiveMQ+redis+Spring+高并发多线程+JVM


高并发多线程面试专题

  • 现在有线程 T1、T2 和 T3。你如何确保 T2 线程在 T1 之后执行,并且 T3 线程在 T2 之后执行?
  • Java 中新的 Lock 接口相对于同步代码块(synchronized block)有什么优势?如果让你实现一个高性能缓存,支持并发读取和单一写入,你如何保证数据完整性。
  • Java 中 wait 和 sleep 方法有什么区别?
  • 如何在 Java 中实现一个阻塞队列?
  • 如何在 Java 中编写代码解决生产者消费者问题?
  • 写一段死锁代码。你在 Java 中如何解决死锁?

高并发多线程面试解析与拓展

BAT面试文档:ActiveMQ+redis+Spring+高并发多线程+JVM


jvm面试专题与解析

  • JVM 由哪些部分组成?
  • JVM 内存划分?
  • Java 的内存模型?
  • 引用的分类?
  • GC什么时候开始?

JVM面试专题解析与拓展!

BAT面试文档:ActiveMQ+redis+Spring+高并发多线程+JVM

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

信息用什么命令?

  • Redis的内存用完了会发生什么?
  • Redis是单线程的,如何提高多核CPU的利用率?

[外链图片转存中…(img-QOzI3Vx7-1715469320938)]


Spring面试专题及答案

  • 谈谈你对 Spring 的理解
  • Spring 有哪些优点?
  • Spring 中的设计模式
  • 怎样开启注解装配以及常用注解
  • 简单介绍下 Spring bean 的生命周期

Spring面试答案解析拓展

[外链图片转存中…(img-FiJ7aHAB-1715469320938)]


高并发多线程面试专题

  • 现在有线程 T1、T2 和 T3。你如何确保 T2 线程在 T1 之后执行,并且 T3 线程在 T2 之后执行?
  • Java 中新的 Lock 接口相对于同步代码块(synchronized block)有什么优势?如果让你实现一个高性能缓存,支持并发读取和单一写入,你如何保证数据完整性。
  • Java 中 wait 和 sleep 方法有什么区别?
  • 如何在 Java 中实现一个阻塞队列?
  • 如何在 Java 中编写代码解决生产者消费者问题?
  • 写一段死锁代码。你在 Java 中如何解决死锁?

高并发多线程面试解析与拓展

[外链图片转存中…(img-svqOj8wS-1715469320938)]


jvm面试专题与解析

  • JVM 由哪些部分组成?
  • JVM 内存划分?
  • Java 的内存模型?
  • 引用的分类?
  • GC什么时候开始?

JVM面试专题解析与拓展!

[外链图片转存中…(img-aOiVPHj8-1715469320939)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 22
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值