微服务项目,在root项目中我用的cloud版本为,其中引用的sentinel版本为
org.springframework.cloud
spring-cloud-dependencies
2021.0.5
pom
import
在业务项目中引入sentinel时
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
直接启动报错,报错信息
Description:
The Bean Validation API is on the classpath but no implementation could be found
Action:
Add an implementation, such as Hibernate Validator, to the classpath
日志说我们缺少一个hibernate-validator包,那就找一个合适的版本依赖一下
org.hibernate.validator
hibernate-validator
6.2.5.Final
启动成功
可以直接下载sentinel-dashboard的jar包, 下载链接
将jar包放到服务器上,启动指令
java -Dserver.port=7777 -Dcsp.sentinel.dashboard.server=localhost:7777 -Dproject.name=sentinel-dashboard -Dsentinel.dashboard.auth.username=sentinel -Dsentinel.dashboard.auth.password=123456 -jar sentinel-dashboard-1.8.6.jar
启动参数解释:
-Dserver.port=8080 // 指定启动端口
-Dcsp.sentinel.dashboard.server=localhost:8080 // 指定服务
-Dproject.name=sentinel-dashboard // 指定sentinel控制台服务的名字
-Dsentinel.dashboard.auth.username=sentinel // 指定sentinel登录名
-Dsentinel.dashboard.auth.password=123456 // 指定sentinel登录密码
在nacos配置文件中添加配置信息,连接sentinel-dashboard
spring:
cloud:
sentinel:
transport:
# sentinel-dashboard的连接地址和端口
dashboard: localhost:7777
# 登录sentinel-dashboard账号密码
username: sentinel
password: 123456
改造代码如下:
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;
/**
* @Classname CustomUrlBlockHandler
* @Description 封装sentinel限流返回值
* @Date 2022/12/4 23:18
* @Author
*/
@Component
public class CustomUrlBlockHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, BlockException ex) throws Exception {
String errCode = null;
if (ex instanceof FlowException) {
errCode = "SDK-SERVER-SENTINEL-FLOW_LIMIT";
} else if (ex instanceof DegradeException) {
errCode = "SDK-SERVER-SENTINEL-DEGRADE_LIMIT";
} else if (ex instanceof ParamFlowException) {
errCode = "SDK-SERVER-SENTINEL-PARAM_LIMIT";
} else if (ex instanceof SystemBlockException) {
errCode = "SDK-SERVER-SENTINEL-SYSTEM_BLOCK";
} else if (ex instanceof AuthorityException) {
errCode = "SDK-SERVER-SENTINEL-AUTHORITY";
}
// http状态码
response.setStatus(HttpStatusEnum.SENTINEL_ERR_STATUS.getCode());
response.setCharacterEncoding("utf-8");
response.setHeader("Content-Type", "application/json;charset=utf-8");
response.setContentType("application/json;charset=utf-8");
// spring mvc自带的json操作工具,叫jackson
response.getWriter().write(JSON.toJSONString(ResultUtil.fail(errCode)));
}
}
主要是解决动态接口参数问题,如接口为"/clean/{id}",根据id不同,url也不同,所以会生成多个拦截。为了处理这种情况添加cleaner处理
@Component
public class CustomerUrlCleaner implements UrlCleaner {
@Override
public String clean(String originUrl) {
if(StringUtils.isEmpty(originUrl)){
return originUrl;
}
if(originUrl.startsWith("/test/")){
return "/test/*";
}
return originUrl;
}
}
因为sentinel-dashboard规则存在于内存里,重启java服务会导致原有的限流熔断规则被重置,所以要进行持久化配置,这里选择使用nacos作为持久化工具。
但是默认情况下sentinel-dashboard可以读取nacos的配置,但是在sentinel-dashboard上配置的规则无法存储到nacos中,
客户端引入依赖
com.alibaba.csp
sentinel-datasource-nacos
1.8.6
添加yml配置
spring:
cloud:
sentinel:
transport:
# sentinel-dashboard的连接地址和端口
dashboard: localhost:7777
# 心跳检测,client的ip和端口
client-ip: 192.168.3.18
port: 8720
# 登录sentinel-dashboard账号密码
username: sentinel
password: 123456
# 配置规则持久化
datasource:
flow:
nacos:
server-addr: ${spring.cloud.nacos.server-addr}
namespace: ${spring.cloud.nacos.config.namespace}
data-id: ${spring.application.name}-sentinel
group-id: ${spring.cloud.nacos.config.group}
# 限流规则
rule-type: flow
data-type: json
username: ${spring.cloud.nacos.username}
password: ${spring.cloud.nacos.password}
degrade:
nacos:
server-addr: ${spring.cloud.nacos.server-addr}
namespace: ${spring.cloud.nacos.config.namespace}
data-id: ${spring.application.name}-sentinel-degrade
group-id: ${spring.cloud.nacos.config.group}
# 熔断规则
rule-type: degrade
data-type: json
username: ${spring.cloud.nacos.username}
password: ${spring.cloud.nacos.password}
# 动态的url,进行过滤
dynamic-url: "['/clean/']"
通过rule-type可以给不同规则设定规则库,如限流规则flow映射到 s p r i n g . a p p l i c a t i o n . n a m e − s e n t i n e l 上,熔断规则映射到 {spring.application.name}-sentinel上,熔断规则映射到 spring.application.name−sentinel上,熔断规则映射到{spring.application.name}-sentinel-degrade上,我们在nacos上创建这两个文件,创建后在其中添加json数据
{
“resource”:"/test", 需要限流的接口
“limitApp”:流控针对的调用来源,若为 default 则不区分调用来源,默认值default,
“grade”:1, 阈值类型:1为QPS,0为线程数
“count”:3, 每秒钟单机阈值,超过就会报错
“strategy”:0, 直接拒绝(默认):接口达到限流条件时,直接限流
关联:当关联的资源达到阈值时,就限流自己(适合做应用让步)
链路:只记录指定链路上的流量,指定资源从入口资源进来的流量,如果达到阈值,就可以限流
“controlBehavior”:0, 设置流控效果 ,快速失败(默认):当 QPS 超过任意规则的阈值后,新的请求就会被立即拒绝,拒绝方式为抛出FlowException
排队等待:这种方式严格控制了请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。
Warm Up:该方式主要用于系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮的情况。预热底层是根据令牌桶算法实现的。
“clusterMode”:false
}
{
resource :资源名,资源名是限流规则的作用对象,比如请求资源 getUser 。
grade :熔断策略,支持慢调用比例/异常比例/异常数策略。1:慢调用比例,2:异常比例,3:异常数。默认为1,慢调用比例。
count :慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用);异常比例/异常数模式下为对应的阈值。
timeWindow :熔断时长,单位为秒。
minRequestAmount :熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断。默认为 5 。
statIntervalMs :统计时长(单位为 ms),如 60*1000 代表分钟级。默认为 1000 ms。
slowRatioThreshold :慢调用比例阈值,仅慢调用比例模式有效
}