赞
踩
实现的步骤:
创建我们流控、限流规则。
然后在被映射的地址去引用。
在 6.3.3 小结中会用到
下载 Jar 包 (sentinel-dashboard-1.8.0.jar)
运行
java -Dserver.port=8718 -Dcsp.sentinel.dashboard.server=localhost:8718 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.0.jar
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
2.1.0.RELEASE
org.springframework.boot
spring-boot-starter-web
@RestController
public class OrderService {
// 定义的限流规则名称
private static final String GETORDER_KEY = “orderToMenber”;
// 测试 Sentinel,对接口限流
@RequestMapping(“/orderToMenber”)
public String orderToMenber() {
Entry entry = null;
try {
entry = SphU.entry(GETORDER_KEY);
return “orderToMenber接口”;
} catch (Exception e) {
// 限流的情况就会进入 Exception
return “当前访问人数过多,请稍后重试!”;
} finally {
if (entry != null) {
entry.exit();
}
}
}
/**
创建限流规则
@return
*/
@RequestMapping(“/initFlowQpsRule”)
public String initFlowQpsRule() {
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);
return “… 限流配置初始化成功”;
}
}
编写启动类 AppOrder
先访问 http://localhost:8080/initFlowQpsRule 实现初始化规则
再访问 http://localhost:8080/orderToMenber
然后看到刷新一遍,接口就会显示 Exception 的异常信息了
QPS:每秒接口的访问次数,设置为 1,每秒接口只能访问一次
必须先加载规则,规则才能生效。
如果 SpringBoot 重启,规则就会失效
SpringBoot 项目启动成功之后,加载我们的限流规则。
Sentinel 限流的规则默认情况下是没有持久化,如果需要持久化的话用 zk、nacos、携程阿波罗
解决方案
package cn.gorit.service.order.config;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Configuration;
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(“>>> 限流配置加载成功”);
}
}
/**
@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 “该接口被限流了”;
}
java -Dserver.port=8718 -Dcsp.sentinel.dashboard.server=localhost:8718 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.0.jar
登录的账号密码:sentinel sentinel
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
/**
基于控制台实现流量规则限流
@return
*/
@RequestMapping(“/getOrderConsole”)
public String getOrderConsole () {
return “getOrderConsole”;
}
/**
*/
Blocked by Sentinel (flow limiting)
PS:如果配置了注解,就会和默认的资源名称冲突,所以要删除默认的资源名称
限流规则设置 线程数
// 基于信号量, 在控制台设置规则的时候,配置为 线程数
@SentinelResource(value = GETORDER_KEY, blockHandler = “getOrderQpsException”)
@RequestMapping(“/getOrderSemaphore”)
public String getOrderSemaphore () {
log.info(“>>>” + Thread.currentThread().getName());
return “getOrderSemaphore”;
}
阙值改为线程数
访问效果
如果看不到效果,可以在代码中加入 Thread.sleep(500) ,使线程阻塞即可
6.4 Sentinel 数据持久化 & 实现服务降级 & 服务熔断
Sentinel 持久化方案
网关整合 Sentinel 实现限流
如何对服务实现动态降级
降级的策略 RT、错误比例、次数
Sentinel 支持数据规则持久化的,官方默认支持 5 种(sentinel-nacos 1.7.0 版本)
nacos 分布式配置中心
携程阿波罗
存放本地文件
Zookeeper
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:
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 持久化被覆盖的问题
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
中提取生成的热点参数规则,根据传入的参数依次进行规则检查。若某条规则不针对请求属性,则会在参数最后一个位置置入预设的常量,达到普通流控的效果。
新建一个 module,并命名为 gorit-gateway
添加依赖
org.springframework.cloud
spring-cloud-starter-gateway
2.2.4.RELEASE
com.alibaba.csp
sentinel-spring-cloud-gateway-adapter
1.7.0
spring:
application:
name: gorit-order-gateway-8080
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
gateway:
routes:
uri: lb://gorit-member
predicates:
Path=/gorit-member/**
id: gorit
uri: https://www.gorit.cn/ # 转发到我的个人网站
predicates:
enabled: true
server:
port: 8080
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();
}
}
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;
/**
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
为了这次面试,也收集了很多的面试题!
以下是部分面试题截图
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Configuration;
import java.util.HashSet;
import java.util.Set;
/**
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。[外链图片转存中…(img-GOPYtDj5-1713325016537)]
[外链图片转存中…(img-D2RMzOCx-1713325016538)]
[外链图片转存中…(img-AfK9Enoc-1713325016538)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
为了这次面试,也收集了很多的面试题!
以下是部分面试题截图
[外链图片转存中…(img-PYyUPHDP-1713325016538)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。