Sentinel的gateway规则持久化改造

Sentinel的gateway规则持久化改造

每天多学一点点~
话不多说,这就开始吧…

文章目录

  • Sentinel的gateway规则持久化改造
  • 1. 前言
  • 2. 源码改造
    • 2.1 老规矩,去掉sentinel-dashboard 工程的pom中test
    • 2.2 复制 test下 NacosConfig类并修改
    • 2.3 新增 pulisher 推送规则 和 provider 拉取规则
    • 2.4 修改GatewayFlowRuleController 和 GatewayApiController
    • 2.5 修改端口
  • 3. 微服务网关改造
  • 4. 持久化测试
  • 5.结语

1. 前言

上篇写过 Sentinel规则持久化改造(pull+push+Ahas),但一般springcloud项目都是与zuul,gateway等网关结合使用,今儿总结下 sentinel 与 gateway的持久化改造。
以sentinel 1.7.0 版本 为例 sentinel git地址

2. 源码改造

2.1 老规矩,去掉sentinel-dashboard 工程的pom中test



    com.alibaba.csp
    sentinel-datasource-nacos
   

2.2 复制 test下 NacosConfig类并修改

修改 Converter

在上篇基础上,加入网关的API和FlowRule

@Configuration
public class NacosConfig {
  /**
     * 流控规则
     *
     * @return
     */
    @Bean
    public Converter, String> flowRuleEntityEncoder() {
        return JSON::toJSONString;
    }

    @Bean
    public Converter> flowRuleEntityDecoder() {
        return s -> JSON.parseArray(s, FlowRuleEntity.class);
    }

    /**
     * 授权规则
     *
     * @return
     */
    @Bean
    public Converter, String> authorRuleEntityEncoder() {
        return JSON::toJSONString;
    }

    @Bean
    public Converter> authorRuleEntityDecoder() {
        return s -> JSON.parseArray(s, AuthorityRuleEntity.class);
    }

    /**
     * 降级规则
     *
     * @return
     */
    @Bean
    public Converter, String> degradeRuleEntityEncoder() {
        return JSON::toJSONString;
    }

    @Bean
    public Converter> degradeRuleEntityDecoder() {
        return s -> JSON.parseArray(s, DegradeRuleEntity.class);
    }

    /**
     * 热点参数 规则
     *
     * @return
     */
    @Bean
    public Converter, String> paramRuleEntityEncoder() {
        return JSON::toJSONString;
    }

    @Bean
    public Converter> paramRuleEntityDecoder() {
        return s -> JSON.parseArray(s, ParamFlowRuleEntity.class);
    }

    /**
     * 系统规则
     *
     * @return
     */
    @Bean
    public Converter, String> systemRuleEntityEncoder() {
        return JSON::toJSONString;
    }

    @Bean
    public Converter> systemRuleEntityDecoder() {
        return s -> JSON.parseArray(s, SystemRuleEntity.class);
    }

    /**
     * 网关API
     *
     * @return
     * @throws Exception
     */
    @Bean
    public Converter, String> apiDefinitionEntityEncoder() {
        return JSON::toJSONString;
    }

    @Bean
    public Converter> apiDefinitionEntityDecoder() {
        return s -> JSON.parseArray(s, ApiDefinitionEntity.class);
    }

    /**
     * 网关flowRule
     *
     * @return
     * @throws Exception
     */
    @Bean
    public Converter, String> gatewayFlowRuleEntityEncoder() {
        return JSON::toJSONString;
    }

    @Bean
    public Converter> gatewayFlowRuleEntityDecoder() {
        return s -> JSON.parseArray(s, GatewayFlowRuleEntity.class);
    }

    @Bean
    public ConfigService nacosConfigService() throws Exception {
        return ConfigFactory.createConfigService("47.111.191.111");
    }
}

2.3 新增 pulisher 推送规则 和 provider 拉取规则

Sentinel的gateway规则持久化改造_第1张图片
**GetWayApiNacosProvider 拉取API **

@Component("getWayApiNacosProvider")
public class GetWayApiNacosProvider implements DynamicRuleProvider> {
    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter> converter;
    @Override
    public List getRules(String appName) throws Exception {
        String rules = configService.getConfig(appName+ NacosConfigUtil.GETWAY_API_DATA_ID_POSTFIX
        ,NacosConfigUtil.GROUP_ID,3000);
        if(StringUtil.isEmpty(rules)){
            return new ArrayList<>();
        }
        return converter.convert(rules);
    }
}

GetWayApiNacosPublisher 推送API

@Component("getWayApiNacosPublisher")
public class GetWayApiNacosPublisher implements DynamicRulePublisher> {
    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter, String> converter;
    @Override
    public void publish(String app, List rules) throws Exception {
        AssertUtil.notEmpty(app, "app name cannot be empty");
        if (rules == null) {
            return;
        }
        configService.publishConfig(app+ NacosConfigUtil.GETWAY_API_DATA_ID_POSTFIX,
                NacosConfigUtil.GROUP_ID,converter.convert(rules));
    }
}

GateWayFlowRulesNacosProvider 拉取规则

@Component("gateWayFlowRulesNacosProvider")
public class GateWayFlowRulesNacosProvider implements DynamicRuleProvider> {

    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter> converter;

    @Override
    public List getRules(String appName) throws Exception {
        String rules = configService.getConfig(appName + NacosConfigUtil.GETWAY_FLOW_DATA_ID_POSTFIX,
                NacosConfigUtil.GROUP_ID, 3000);
        if (StringUtil.isEmpty(rules)) {
            return new ArrayList<>();
        }
        return converter.convert(rules);
    }

}

GateWayFlowRulesNacosPunlisher 推送规则

@Component("gateWayFlowRulesNacosPunlisher")
public class GateWayFlowRulesNacosPunlisher implements DynamicRulePublisher> {

    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter, String> converter;


    @Override
    public void publish(String app, List rules) throws Exception {
        AssertUtil.notEmpty(app, "app name cannot be empty");
        if (rules == null) {
            return;
        }
        configService.publishConfig(app + NacosConfigUtil.GETWAY_FLOW_DATA_ID_POSTFIX,
                NacosConfigUtil.GROUP_ID, converter.convert(rules));
    }
}

2.4 修改GatewayFlowRuleController 和 GatewayApiController

  1. 注入上文我们自己写的 GetWayApiNacosProvider 和 GetWayApiNacosPublisher
//添加我们自己写的ruleProvider
@Autowired
@Qualifier("gateWayFlowRuleNacosProvider")
private DynamicRuleProvider> ruleProvider;

//添加我们自己写的 publisher
@Autowired
@Qualifier("gateWayFlowRuleNacosPubisher")
private DynamicRulePublisher> rulePublisher;
  1. 以 @GetMapping("/list.json") 为例,修改代码
// 原生方法 拉取网关微服务
// List rules = sentinelApiClient.fetchGatewayFlowRules(app, ip, port).get();
// 现修改 ---> 去配置中心拉取
List rules = ruleProvider.getRules(app);

其他 Mapping 同理

  1. 新增方法,发布到nacos上
GatewayApiController 类
   /**
     *  api 推送 到 nacos
     * @param app
     * @throws Exception
     */
    private void publishApis(String app) throws Exception {
        List rules = repository.findAllByApp(app);
        rulePublisher.publish(app,rules);
    }

GatewayFlowRuleController 类
  /**
     * 把配置推给nacos中
     *
     * @param app
     * @throws Exception
     */
    private void publishRules(String app) throws Exception {
        List rules = repository.findAllByApp(app);
        rulePublisher.publish(app, rules);
    }
  1. 修改GatewayApiController 和 GatewayFlowRuleController 的 @PostMapping("/new.json") @PostMapping("/save.json") @PostMapping("/delete.json") 都是一样的改造
entity = repository.save(entity); // 保存到内存中
// 推送给微服务
//  publishRules(entity.getApp(), entity.getIp(), entity.getPort());
// 现通过 自己的publisher推送到配置中心
publishRules(entity.getApp());
  1. 修改 NacosConfigUtil
public final class NacosConfigUtil {

    public static final String GROUP_ID = "SENTINEL_GROUP";
    
    public static final String FLOW_DATA_ID_POSTFIX = "-flow-rules";
    public static final String DEGRAD_DATA_ID_POSTFIX = "-degrade-rules";
    public static final String AUTH_DATA_ID_POSTFIX = "-authority-rules";
    public static final String SYS_DATA_ID_POSTFIX = "-system-rules";
    public static final String PARAM_FLOW_DATA_ID_POSTFIX = "-param-rules";
    public static final String CLUSTER_MAP_DATA_ID_POSTFIX = "-cluster-map";
    public static final String GETWAY_API_DATA_ID_POSTFIX = "-getway-api";
    public static final String GETWAY_FLOW_DATA_ID_POSTFIX = "-getway-flow";

    /**
     * cc for `cluster-client`
     */
    public static final String CLIENT_CONFIG_DATA_ID_POSTFIX = "-cc-config";
    /**
     * cs for `cluster-server`
     */
    public static final String SERVER_TRANSPORT_CONFIG_DATA_ID_POSTFIX = "-cs-transport-config";
    public static final String SERVER_FLOW_CONFIG_DATA_ID_POSTFIX = "-cs-flow-config";
    public static final String SERVER_NAMESPACE_SET_DATA_ID_POSTFIX = "-cs-namespace-set";

    private NacosConfigUtil() {}
}

此时,GatewayFlowRuleController 已经改造完毕。喜大普奔23333

2.5 修改端口

如果是集群,修改为nginx的地址
Sentinel的gateway规则持久化改造_第2张图片

3. 微服务网关改造

  1. 加入依赖


   com.alibaba.csp
   sentinel-datasource-nacos

  1. yml配置
# 新增持久化配置 
server:
  port: 8888
spring:
  application:
    name: gateway-sentinel
  cloud:
    gateway:
      discovery:
        locator:
          lower-case-service-id: true
          enabled: true
      routes:
        - id: product_center
          uri: lb://product-center
          predicates:
            - Path=/product/**     
        - id: order_center
          uri: lb://order-center
          predicates:
            - Path=/order/**
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:9999
      datasource:
        # 名称随意
        gw-flow:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-gateway-flow # 在修改的sentinel 源码中定义的规则名
            groupId: SENTINEL_GROUP
            rule-type: gw-flow
        gw-api-group:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-gateway-api # 在修改的sentinel 源码中定义的规则名
            groupId: SENTINEL_GROUP
            rule-type: gw-api-group
  main:
    allow-bean-definition-overriding: true

4. 持久化测试

启动 订单微服务工程(啥也没有,就是一个接口查db) 和网关微服务工程,启动sentinel源码 地址 http://localhost:9999/#/login

先访问一次网关接口 http://localhost:8888/product/selectProductInfoById/1

http://localhost:9999/#/dashboard (sentinel 控制台)
Sentinel的gateway规则持久化改造_第3张图片

配置流控

再看nacos
Sentinel的gateway规则持久化改造_第4张图片

多次访问 网关接口被限流了

最后,重启 gateway or sentinel 规则还在~ 在nacos或者sentinel控制台 改规则,两边都能同步
继续多次刷网关接口,显示被限流

大功告成~

5.结语

世上无难事,只怕有心人,每天积累一点点,fighting!!!

你可能感兴趣的:(sentinel,gateway,持久化改造,springcloud,alibaba)