Home
dengsixing このページを編集 3 年 前

项目概述:

该项目是在sentinel官方项目源码基础上加以改造,官方项目的规则是保存在内存中的,业务应用重启后,限流规则、熔断规则会丢失。

而改造后持久化到实现限流规则、熔断规则持久化到nacos,解决了丢失问题,同时也实现双向推拉的效果,在sentinel控制台对规则进行CRUD操作会推送到Nacos,反义毅然。

目前只改造了限流、熔断规则,如需其它规则,请自行实现

改造内容:

  1. 修改application.properties文件,增加配置:
nacos.address=192.168.0.47:8848
nacos.namespace=4dkankan-dev
nacos.username=nacos
nacos.password=nacos
  1. 在com.alibaba.csp.sentinel.dashboard.rule包下增加持久化nacos实现代码如下:
NacosConfig               #nacos配置
NacosConfigUtil           #nacos持久化逻辑工具  
DegradeRuleNacosProvider  #熔断规则拉取接口
DegradeRuleNacosPublisher #熔断规则推送接口
FlowRuleNacosProvider     #限流规则拉取接口
FlowRuleNacosPublisher    #限流规则推送接口

3.改造控制器 改造DegradeController,注入并调用DegradeRuleNacosProvider、DegradeRuleNacosPublisher实现nacos推拉效果 改造FlowControllerV2,注入并调用FlowRuleNacosProvider、FlowRuleNacosPublisher实现nacos推拉效果

4.改造sidebar.html 注释以下代码

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

打开原有注释掉的以下代码,如果没有就增加

<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;流控规则</a>
</li>

使用教程

sentinel-dashboard部署

1.修改配置文件

sentinel-dashboard-nacos\sentinel-dashboard\src\main\resources\application.properties,修改内容如下
nacos.address=<ip>:<port>
nacos.namespace=xxxx
nacos.username=xxxx
nacos.password=xxxx

2.打jar包,springboot方式打包

3.启动控制台

启动命令:

java -Dserver.port=8080 
-Dcsp.sentinel.dashboard.server=localhost:8080 
-Dproject.name=sentinel-dashboard 
-jar target/sentinel-dashboard.jar

上述命令中我们指定几个 JVM 参数,其中 -Dserver.port=8080 是 Spring Boot 的参数, 用于指定 Spring Boot 服务端启动端口为 8080。其余几个是 Sentinel 客户端的参数。

为便于演示,我们对控制台本身加入了流量控制功能,具体做法是引入 Sentinel 提供的 CommonFilter 这个 Servlet Filter。 上述 JVM 参数的含义是:

-Dcsp.sentinel.dashboard.server=localhost:8080 向 Sentinel 接入端指定控制台的地址

-Dproject.name=sentinel-dashboard 向 Sentinel 指定应用名称,比如上面对应的应用名称就为 sentinel-dashboard

客户端接入

pom依赖:

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

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

1.配置文件增加如下配置:

spring:
    cloud:
        sentinel:
          transport:
            dashboard: 192.168.0.47:8888
            heartbeat-interval-ms: 500
            port: 8719
          eager: true #取消sentinel控制台懒加载
          #sentinel配置持久化nacos
          datasource:
            #流控规则
            flow:
              nacos:
                server-addr: ${spring.cloud.nacos.config.server-addr}
                dataId: ${spring.application.name}-flow-rules
                groupId: SENTINEL_GROUP
                namespace: 4dkankan-dev
                rule-type: flow
            #熔断规则
            degrade:
              nacos:
                server-addr: ${spring.cloud.nacos.config.server-addr}
                dataId: ${spring.application.name}-degrade-rules
                groupId: SENTINEL_GROUP
                namespace: 4dkankan-dev
                rule-type: degrade

2.增加限流熔断异常处理器,代码如下:

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.fasterxml.jackson.databind.ObjectMapper;
import com.fdkankan.common.response.ResultData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * <p>
 * sentinel统一异常处理
 * </p>
 *
 * @author dengsixing
 * @since 2022/1/26
 **/
@Slf4j
@Component
public class SentinelUrlBlockHandler implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws IOException {
        String msg = null;
        if (e instanceof FlowException) {
            msg = "限流了";
        } else if (e instanceof DegradeException) {
            msg = "降级了";
        } else if (e instanceof ParamFlowException) {
            msg = "热点参数限流";
        } else if (e instanceof SystemBlockException) {
            msg = "系统规则(负载/...不满足要求)";
        } else if (e instanceof AuthorityException) {
            msg = "授权规则不通过";
        }
        // http状态码
        response.setStatus(500);
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-Type", "application/json;charset=utf-8");
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);

        new ObjectMapper()
                .writeValue(
                        response.getWriter(),
                        ResultData.error(-1, msg)
                );
    }
}

网关接入:

1、pom依赖:

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

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
    <version>1.7.2</version>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>

2、增加配置类:

@Configuration
@Order(2)
public class SentinelPersistenceConfig {

    @Autowired
    private SentinelProperties sentinelProperties;

    @Bean
    public SentinelPersistenceConfig init() throws Exception {
        loadGWFlowRule();
        return new SentinelPersistenceConfig();
    }

    private void loadGWFlowRule() {
        sentinelProperties.getDatasource().entrySet().stream().filter(map -> {
            return map.getValue().getNacos() != null;
        }).forEach(map -> {
            NacosDataSourceProperties nacos = map.getValue().getNacos();
            ReadableDataSource<String, Set<GatewayFlowRule>> gwFlowRuleDataSource = new NacosDataSource<>(
                    nacos.getServerAddr(), nacos.getGroupId(), nacos.getDataId(),
                    source -> JSON.parseObject(source, new TypeReference<Set<GatewayFlowRule>>() {
                    }));
            GatewayRuleManager.register2Property(gwFlowRuleDataSource.getProperty());
        });
    }
}

3、配置文件增加如下配置:

spring:
  application:
    name: 4dkankan-gateway
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8888
        heartbeat-interval-ms: 500
        port: 8719
      eager: true #取消sentinel控制台懒加载
      #sentinel配置持久化nacos
      datasource:
        #流控规则
        flow:
          nacos:
            server-addr: ${spring.cloud.nacos.config.server-addr}
            dataId: ${spring.application.name}-flow-rules
            groupId: SENTINEL_GROUP
            namespace: 4dkankan-test
            rule-type: flow
        gw_api_group:
          nacos:
            server-addr: ${spring.cloud.nacos.config.server-addr}
            dataId: ${spring.application.name}-api-group-rules
            groupId: SENTINEL_GROUP
            namespace: 4dkankan-test
            rule-type: gw_api_group
      #配置限流之后的响应内容,这里也可以替换为自定义限流处理器进行限流响应统一返回
      scg:
        fallback:
          #两种模式:一种是response返回文字提示信息,一种是redirect,重定向跳转,需要同时配置redirect(跳转的uri)
          mode: response
          #响应的状态
          response-status: 426
          #响应体
          response-body: '{"code": 426,"message": "限流了,稍后重试!"}'

4、自定义限流异常处理类


#限流异常处理类
public class SentinelBlockRequestHandler implements BlockRequestHandler {

    @Override
    public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable t) {
        return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS)
                .contentType(MediaType.APPLICATION_JSON)
                .body(fromValue(ResultData.error(ErrorCode.SYSTEM_BUSY)));
    }
}

#初始化限流处理器
@Configuration
public class SentinelBlockRequestHandlerInitConfig implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        log.info("初始化限流handler");
        GatewayCallbackManager.setBlockHandler(new SentinelBlockRequestHandler());
    }
}

控制台使用

在流控规则栏目新增流控规则,会在nacos配置中心生成对应的应用流控规则,Data Id命名规则为:<应用名>-flow-rules

在熔断规则栏目新增熔断规则,会在nacos配置中心生成对应的应用流控规则,Data Id命名规则为:<应用名>-degrade-rules

其他规则毅然...

注意事项

如果你的项目中有全局异常处理器捕获Exception,需要在异常处理逻辑中增加一下代码:

com.alibaba.csp.sentinel.Tracer.trace(e);

这行代码的作用是:增加sentinel异常次数

否则异常被异常处理吞没,sentinel无法统计异常次数,导致熔断规则失效