赞
踩
可以使用官方的sentinel
也可使用进行持久化改造后的Sentinel ,本文基于此进行记录。Sentinel持久化到Nacoshttps://blog.csdn.net/chenjian723122704/article/details/130098896
Sentinel版本为 1.8.6
Nacos版本为 2.2.0
关于网关限流、限流和熔断,我自己总结出来了一套规则,有更好的意见希望大家指正。
- 网关只做限流,不做熔断。
- 普通服务被请求,比如客户请求我们的api服务,此时做限流。
- 普通服务调用内部服务,比如API服务,调用账单查询服务,需要做两部操作。1)在api服务的配置文件打开 feign.sentinel.enable=true;2)账单查询服务需要配置熔断规则。 当api的请求账单服务的接口达到熔断的阈值时,api下次再有请求,就会直接进入降级方法,或者抛出异常。
java -jar sentinel-dashboard-1.8.6.jar --server.port=8800
新建一个Springboot应用,创建一个用于测试的Controller
- /**
- * 测试
- * @author chenjian
- * @date 2022/12/30
- * @version 1.0
- */
- @Slf4j
- @RefreshScope
- @RestController
- @RequestMapping("/test")
- public class Test {
- @GetMapping("/test")
- public R test() {
- return R.ok();
- }
- }
-
-
- /**
- * 返回数据
- *
- * @author jianchene0
- */
- @Slf4j
- public class R extends HashMap<String, Object> {
- private static final long serialVersionUID = 1L;
-
- public R() {
- put("code", 0);
- put("msg", "success");
- }
-
- public static R error() {
- return error(500, "未知异常,请联系管理员");
- }
-
- public static R error(String msg) {
- return error(500, msg);
- }
-
- public static R error(int code, String msg) {
- R r = new R();
- r.put("code", code);
- r.put("msg", msg);
-
- log.error("失败信息: "+ code + " ---- " + msg);
- return r;
- }
-
- public static R ok(String msg) {
- R r = new R();
- r.put("msg", msg);
- return r;
- }
-
- public static R ok(Map<String, Object> map) {
- R r = new R();
- r.putAll(map);
- return r;
- }
-
- public static R ok() {
- return new R();
- }
-
- @Override
- public R put(String key, Object value) {
- super.put(key, value);
- return this;
- }
-
- /**
- * 检查是否OK
- * @return
- */
- public boolean isOk() {
- return (int)this.get("code") == 0;
- }
- }
pom文件中引入依赖
-
- <!-- Sentinel流量监控、限流、熔断降级处理 -->
- <dependency>
- <groupId>com.alibaba.cloud</groupId>
- <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
- </dependency>
若使用改造的支持持久化的Sentinel,还需要引入依赖
<!-- 引入Nacos数据源 --> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> <version>${sentinel.version}</version> </dependency>
yaml引入sentinel配置、nacos配置及其他配置
- # Tomcat
- server:
- tomcat:
- uri-encoding: UTF-8
- port: 9803
- servlet:
- context-path: /
-
- spring:
- application:
- name: api
- cloud:
- nacos:
- # nacos.core.auth.enabled=true 开启权限验证
- discovery:
- # nacos地址
- server-addr: 127.0.0.1:8848
- username: nacos
- password: nacos
- namespace:
- group: DEFAULT_GROUP
- metadata:
- management:
- context-path: ${server.servlet.context-path}/actuator
- config:
- server-addr: 127.0.0.1:8848
- username: nacos
- password: nacos
- #data-id后缀
- file-extension: yaml
- # 分组名称
- namespace:
- group: DEFAULT_GROUP
- encode: UTF-8
- # 修改后自动加载
- refresh-enabled: true
- # 允许nacos服务端向本地同步配置
- enable-remote-sync-config: true
- sentinel:
- eager: true #是否开启网关限流,默认true
- transport:
- # 添加sentinel的控制台地址
- dashboard: 127.0.0.1:8800
- #指定应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用的HttpServer
- # port: 8719
- web-context-unify: false # 默认将调用链路收敛,导致链路流控效果无效
- # 持久化配置
- datasource:
- flow-rule: # 唯一名称可自定义
- nacos:
- # 设置Nacos的连接地址、命名空间和Group ID
- server-addr: ${spring.cloud.nacos.discovery.server-addr}
- username: ${spring.cloud.nacos.discovery.username}
- password: ${spring.cloud.nacos.discovery.password}
- namespace: # 为空,使用默认的public
- # 设置Nacos中配置文件的命名规则
- dataId: ${spring.application.name}-flow-rules
- groupId: SENTINEL_GROUP
- data-type: json
- # 必填的重要字段,指定当前规则类型是"限流"
- rule-type: flow
- degrade-rule: # 唯一名称可自定义
- nacos:
- # 设置Nacos的连接地址、命名空间和Group ID
- server-addr: ${spring.cloud.nacos.discovery.server-addr}
- username: ${spring.cloud.nacos.discovery.username}
- password: ${spring.cloud.nacos.discovery.password}
- namespace: # 为空,使用默认的public
- # 设置Nacos中配置文件的命名规则
- dataId: ${spring.application.name}-degrade-rules
- groupId: SENTINEL_GROUP
- data-type: json
- # 必填的重要字段,指定当前规则类型是"限流"
- rule-type: degrade
- system-rule: # 唯一名称可自定义
- nacos:
- # 设置Nacos的连接地址、命名空间和Group ID
- server-addr: ${spring.cloud.nacos.discovery.server-addr}
- username: ${spring.cloud.nacos.discovery.username}
- password: ${spring.cloud.nacos.discovery.password}
- namespace: # 为空,使用默认的public
- # 设置Nacos中配置文件的命名规则
- dataId: ${spring.application.name}-system-rules
- groupId: SENTINEL_GROUP
- data-type: json
- # 必填的重要字段,指定当前规则类型是"限流"
- rule-type: system
- param-flow-rule: # 唯一名称可自定义
- nacos:
- # 设置Nacos的连接地址、命名空间和Group ID
- server-addr: ${spring.cloud.nacos.discovery.server-addr}
- username: ${spring.cloud.nacos.discovery.username}
- password: ${spring.cloud.nacos.discovery.password}
- namespace: # 为空,使用默认的public
- # 设置Nacos中配置文件的命名规则
- dataId: ${spring.application.name}-param-flow-rules
- groupId: SENTINEL_GROUP
- data-type: json
- # 必填的重要字段,指定当前规则类型是"限流"
- rule-type: param-flow
- authority-rule: # 唯一名称可自定义
- nacos:
- # 设置Nacos的连接地址、命名空间和Group ID
- server-addr: ${spring.cloud.nacos.discovery.server-addr}
- username: ${spring.cloud.nacos.discovery.username}
- password: ${spring.cloud.nacos.discovery.password}
- namespace: # 为空,使用默认的public
- # 设置Nacos中配置文件的命名规则
- dataId: ${spring.application.name}-authority-rules
- groupId: SENTINEL_GROUP
- data-type: json
- # 必填的重要字段,指定当前规则类型是"限流"
- rule-type: authority
-
- feign:
- sentinel:
- enabled: true #sentinel是不会对feign进行监控的,需要开启配置
-
此外,定义Sentinel的异常处理器,使得当被限流、降级时,可以同一返回异常信息
- import com.ah.ums.common.constants.ResCodeEnum;
- import com.ah.ums.common.utils.R;
- import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
- 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.alibaba.fastjson.JSON;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import org.springframework.stereotype.Component;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
-
- /**
- * sentinel 限流降级后异常处理
- * @author jianchen
- */
- @Component
- public class SentinelExceptionHandler implements BlockExceptionHandler {
- @Override
- public void handle(HttpServletRequest request, HttpServletResponse response, BlockException ex) throws Exception {
- ResCodeEnum resCodeEnum = null;
- if (ex instanceof FlowException) {
- resCodeEnum = ResCodeEnum.SENTINEL_FLOW_ERROR;
- } else if (ex instanceof DegradeException) {
- resCodeEnum = ResCodeEnum.SENTINEL_DEGRADE_ERROR;
- } else if (ex instanceof ParamFlowException) {
- resCodeEnum = ResCodeEnum.SENTINEL_PARAM_FLOW_ERROR;
- } else if (ex instanceof SystemBlockException) {
- resCodeEnum = ResCodeEnum.SENTINEL_SYSTEM_ERROR;
- } else if (ex instanceof AuthorityException) {
- resCodeEnum = ResCodeEnum.SENTINEL_AUTHORITY_ERROR;
- }
- // http状态码
- response.setCharacterEncoding("utf-8");
- response.setHeader("Content-Type", "application/json;charset=utf-8");
- response.setContentType("application/json;charset=utf-8");
- String errJson = JSON.toJSONString(R.error(resCodeEnum.getCode(), resCodeEnum.getMsg()));
- new ObjectMapper().writeValue(response.getWriter(), errJson);
- }
- }
-
-
- /**
- * 返回码枚举
- *
- * @author chenjian
- * @version 1.0
- * @date 2022/11/11
- */
- public enum ResCodeEnum {
- ok(0, "成功"),
- NO_PARAM(201, "传入参数缺失,请检查"),
- ERR_PARAM(202, "传入参数异常,请检查"),
- VALID_FAIL_PARAM(203, "参数校验异常"),
- SENTINEL_FLOW_ERROR(427, "请求过于频繁,被限流了"),
- SENTINEL_DEGRADE_ERROR(428, "请求过于频繁,被降级了"),
- SENTINEL_PARAM_FLOW_ERROR(429, "热点数据请求过于频繁"),
- SENTINEL_SYSTEM_ERROR(430, "请求过于频繁,触发系统限制"),
- SENTINEL_AUTHORITY_ERROR(431, "授权规则不通过"),
- UNKNOWN(999, "操作失败!!");
- private Integer code;
- private String msg;
-
- ResCodeEnum(Integer code, String msg) {
- this.code = code;
- this.msg = msg;
- }
-
- public Integer getCode() {
- return code;
- }
-
- public String getMsg() {
- return msg;
- }
-
- public static ResCodeEnum getByCode(Integer code) {
- if (code == null) {
- return null;
- }
- for (ResCodeEnum resMsgEnum : values()) {
- if(resMsgEnum.code.equals(code)) {
- return resMsgEnum;
- }
- }
- return UNKNOWN;
- }
- }
至此,普通服务改造完成,可以使用Sentinel进行监控了
访问成功后 ,会在Sentinel的控制台看到有api的请求进来了
此时会发现nacos中会自动增肌了一条配置,里面记录了api的流控规则
我们接着测试,在浏览器不停刷新刚刚的链接,会出现限流的提示,此时,我们的url就被限流了
假设有两个服务,都是按照第2节配置了Sentinel的依赖、yaml。:
一般的规则时 API服务通过openFeign调用service提供的服务。使用feign注意的是 API 一定要配置 feign.sentinel.enable=true ,否则熔断效果不会生效。
在 Feign定义处,加上fallback。
对应的fallback
在Sentinel增加一条熔断规则,2秒内溢出比例达到0.2就进行熔断。
我们在服务内部加上 int a = 10/0;然后再让API请求查询用户分页数据。就会出发熔断,进入回调方法。
网关限流与第2节中的配置基本类似,不过需要增加网关相关的依赖和配置,以及增加启动参数。
- <!-- 引入Nacos数据源 -->
- <dependency>
- <groupId>com.alibaba.csp</groupId>
- <artifactId>sentinel-datasource-nacos</artifactId>
- <version>${sentinel.version}</version>
- </dependency>
- <!-- Sentinel流量监控、限流、熔断降级处理 -->
- <dependency>
- <groupId>com.alibaba.cloud</groupId>
- <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
- </dependency>
- <!-- gateway网关整合sentinel进行限流降级 -->
- <dependency>
- <groupId>com.alibaba.cloud</groupId>
- <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
- </dependency>
网关持久化依赖
- spring:
- cloud:
- sentinel:
- datasource:
- gw-flow-rule: # 唯一名称可自定义
- nacos:
- # 设置Nacos的连接地址、命名空间和Group ID
- server-addr: ${spring.cloud.nacos.discovery.server-addr}
- username: ${spring.cloud.nacos.discovery.username}
- password: ${spring.cloud.nacos.discovery.password}
- namespace: # 为空,使用默认的public
- # 设置Nacos中配置文件的命名规则
- dataId: ${spring.application.name}-gw-flow-rules
- groupId: SENTINEL_GROUP
- data-type: json
- # 必填的重要字段,指定当前规则类型是"限流"
- rule-type: gw-flow
- gw-api-group: # 唯一名称可自定义
- nacos:
- # 设置Nacos的连接地址、命名空间和Group ID
- server-addr: ${spring.cloud.nacos.discovery.server-addr}
- username: ${spring.cloud.nacos.discovery.username}
- password: ${spring.cloud.nacos.discovery.password}
- namespace: # 为空,使用默认的public
- # 设置Nacos中配置文件的命名规则
- dataId: ${spring.application.name}-gw-api-groups
- groupId: SENTINEL_GROUP
- data-type: json
- # 必填的重要字段,指定当前规则类型是"限流"
- rule-type: gw-api-group
完整的网关yaml配置
- # Tomcat
- server:
- tomcat:
- uri-encoding: UTF-8
- port: 9803
- servlet:
- context-path: /
-
- spring:
- application:
- name: api
- cloud:
- gateway:
- # 路由数组:指当请求满足什么样的断言时,转发到哪个服务上
- routes:
- # 配置断言路由到 API 服务中
- # 路由标识,要求唯一,名称任意
- - id: api
- uri: lb://api # 使用了lb形式,从注册中心负载均衡的获取uri
- # 设置断言
- predicates:
- # 断言,满足 /api/** 路径的请求都会被路由到 API 服务中
- - Path=/api/**
- filters:
- - StripPrefix=1 # 去除url的第一个前缀,本规则是去除/api
- nacos:
- # nacos.core.auth.enabled=true 开启权限验证
- discovery:
- # nacos地址
- server-addr: 127.0.0.1:8848
- username: nacos
- password: nacos
- namespace:
- group: DEFAULT_GROUP
- metadata:
- management:
- context-path: ${server.servlet.context-path}/actuator
- config:
- server-addr: 127.0.0.1:8848
- username: nacos
- password: nacos
- #data-id后缀
- file-extension: yaml
- # 分组名称
- namespace:
- group: DEFAULT_GROUP
- encode: UTF-8
- # 修改后自动加载
- refresh-enabled: true
- # 允许nacos服务端向本地同步配置
- enable-remote-sync-config: true
- sentinel:
- eager: true #是否开启网关限流,默认true
- #配置限流之后的响应内容
- scg:
- fallback:
- # 两种模式:一种是response返回文字提示信息,一种是redirect,重定向跳转
- mode: response
- # 响应的状态
- response-status: 426
- # 响应体
- response-body: '{"code": 426,"message": "限流了,稍后重试!"}'
- transport:
- # 添加sentinel的控制台地址
- dashboard: 127.0.0.1:8800
- #指定应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用的HttpServer
- # port: 8719
- web-context-unify: false # 默认将调用链路收敛,导致链路流控效果无效
- # 持久化配置
- datasource:
- flow-rule: # 唯一名称可自定义
- nacos:
- # 设置Nacos的连接地址、命名空间和Group ID
- server-addr: ${spring.cloud.nacos.discovery.server-addr}
- username: ${spring.cloud.nacos.discovery.username}
- password: ${spring.cloud.nacos.discovery.password}
- namespace: # 为空,使用默认的public
- # 设置Nacos中配置文件的命名规则
- dataId: ${spring.application.name}-flow-rules
- groupId: SENTINEL_GROUP
- data-type: json
- # 必填的重要字段,指定当前规则类型是"限流"
- rule-type: flow
- degrade-rule: # 唯一名称可自定义
- nacos:
- # 设置Nacos的连接地址、命名空间和Group ID
- server-addr: ${spring.cloud.nacos.discovery.server-addr}
- username: ${spring.cloud.nacos.discovery.username}
- password: ${spring.cloud.nacos.discovery.password}
- namespace: # 为空,使用默认的public
- # 设置Nacos中配置文件的命名规则
- dataId: ${spring.application.name}-degrade-rules
- groupId: SENTINEL_GROUP
- data-type: json
- # 必填的重要字段,指定当前规则类型是"限流"
- rule-type: degrade
- system-rule: # 唯一名称可自定义
- nacos:
- # 设置Nacos的连接地址、命名空间和Group ID
- server-addr: ${spring.cloud.nacos.discovery.server-addr}
- username: ${spring.cloud.nacos.discovery.username}
- password: ${spring.cloud.nacos.discovery.password}
- namespace: # 为空,使用默认的public
- # 设置Nacos中配置文件的命名规则
- dataId: ${spring.application.name}-system-rules
- groupId: SENTINEL_GROUP
- data-type: json
- # 必填的重要字段,指定当前规则类型是"限流"
- rule-type: system
- param-flow-rule: # 唯一名称可自定义
- nacos:
- # 设置Nacos的连接地址、命名空间和Group ID
- server-addr: ${spring.cloud.nacos.discovery.server-addr}
- username: ${spring.cloud.nacos.discovery.username}
- password: ${spring.cloud.nacos.discovery.password}
- namespace: # 为空,使用默认的public
- # 设置Nacos中配置文件的命名规则
- dataId: ${spring.application.name}-param-flow-rules
- groupId: SENTINEL_GROUP
- data-type: json
- # 必填的重要字段,指定当前规则类型是"限流"
- rule-type: param-flow
- authority-rule: # 唯一名称可自定义
- nacos:
- # 设置Nacos的连接地址、命名空间和Group ID
- server-addr: ${spring.cloud.nacos.discovery.server-addr}
- username: ${spring.cloud.nacos.discovery.username}
- password: ${spring.cloud.nacos.discovery.password}
- namespace: # 为空,使用默认的public
- # 设置Nacos中配置文件的命名规则
- dataId: ${spring.application.name}-authority-rules
- groupId: SENTINEL_GROUP
- data-type: json
- # 必填的重要字段,指定当前规则类型是"限流"
- rule-type: authority
- gw-flow-rule: # 唯一名称可自定义
- nacos:
- # 设置Nacos的连接地址、命名空间和Group ID
- server-addr: ${spring.cloud.nacos.discovery.server-addr}
- username: ${spring.cloud.nacos.discovery.username}
- password: ${spring.cloud.nacos.discovery.password}
- namespace: # 为空,使用默认的public
- # 设置Nacos中配置文件的命名规则
- dataId: ${spring.application.name}-gw-flow-rules
- groupId: SENTINEL_GROUP
- data-type: json
- # 必填的重要字段,指定当前规则类型是"限流"
- rule-type: gw-flow
- gw-api-group: # 唯一名称可自定义
- nacos:
- # 设置Nacos的连接地址、命名空间和Group ID
- server-addr: ${spring.cloud.nacos.discovery.server-addr}
- username: ${spring.cloud.nacos.discovery.username}
- password: ${spring.cloud.nacos.discovery.password}
- namespace: # 为空,使用默认的public
- # 设置Nacos中配置文件的命名规则
- dataId: ${spring.application.name}-gw-api-groups
- groupId: SENTINEL_GROUP
- data-type: json
- # 必填的重要字段,指定当前规则类型是"限流"
- rule-type: gw-api-group
-
-
-
启动网关应用,访问一次路由地址 http://localhost/api/test/test?params=1
在Sentinel的控制台能到网关的请求。
点击流控,
测试根据Route Id进行限流,先设置限流规则
刷新页面,会提示限流 http://localhost/api/test/test?params=1
根据API分组限流,首先需要在API管理中设置
在流控设置中可以选择对应的分组
删除原来的网关限流规则,使用新的规则,测试限流
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。