springcloud配置sentinel结合gateway,nacos进行pash推送动态来配置sentinel限流规则等

一:导入相关依赖

    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <!--配置中心-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>
    <!--sentinel-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>
    <!---本地连接sentinel-->
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-transport-simple-http</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-core</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-datasource-nacos</artifactId>
    </dependency>

二:创建bootstrap.yml文件

#默认端口
server:
  port: 30000
#自定义参数
nacos:
  server-addr: 127.0.0.1:40002
sentinel:
  server-addr: 127.0.0.1:40008
spring:
  main:
    #支持名称相同的bean被覆盖
    allow-bean-definition-overriding: true
  #环境配置
  profiles:
    active: local
  #name
  application:
    name: ljq-gateway
  #nacos配置
  cloud:
    nacos:
      discovery:
        server-addr: ${nacos.server-addr} #注册中心
        #不配置默认加载public的 配置加载自己命名空间
        namespace: ${spring.profiles.active} #命名空间id
        group: ${spring.profiles.active}
      config:
        server-addr: ${nacos.server-addr}  #配置中心
        group: ${spring.profiles.active}  #分组  默认分组
        file-extension: yaml #类型
        namespace: ${spring.profiles.active} #命名空间id
        #多个dataID加载多个配置文件
        ext-config[0]:
          data-id: application-common.yaml
          group: ${spring.profiles.active} #公用分组
          refresh: true #动态刷新
    #sentinel
    sentinel:
      transport:
        dashboard: ${sentinel.server-addr}
      eager: true  #开启客户端懒加载
      datasource:
        ds:
          nacos:
            server-addr: ${nacos.server-addr} #nacos连接
            groupId: ${spring.profiles.active}  #分组  默认分组
            file-extension: json #类型
            namespace: ${spring.profiles.active} #命名空间id
            rule-type: flow #该参数是spring cloud alibaba升级到0.2.2之后增加的配置,用来定义存储的规则类型。所有的规则类型可查看枚举类:
            dataId: ${spring.application.name}-sentinel

三:配置nacos相关内容
1.1:配置命名空间:
在这里插入图片描述
1.2:配置配置管理
在这里插入图片描述
1.3 配置限流规则:
在这里插入图片描述
四:配置gateway

package com.ljq.gateway.config;

import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
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.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.*;

/**
 * 配置gateway规则
 *
 * @author hxy_admin
 */
@Configuration
public class GatewayConfiguration {
    private final List<ViewResolver> viewResolvers;
    private final ServerCodecConfigurer serverCodecConfigurer;

    /**
     * 网关配置
     *
     * @param viewResolversProvider
     * @param serverCodecConfigurer
     */
    public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,
                                ServerCodecConfigurer serverCodecConfigurer) {
        this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
        this.serverCodecConfigurer = serverCodecConfigurer;
    }

    /**
     * 哨兵网关块异常处理程序
     *
     * @return
     */
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
        // Register the block exception handler for Spring Cloud Gateway.
        return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    }

    /**
     * 哨兵网关过滤器
     *
     * @return
     */
    @Bean
    @Order(-1)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }

    /**
     * 初始化
     */
    @PostConstruct
    public void doInit() {
        //自定义限流规则Apis
        initCustomizedApis();
        //自定义的 API 定义分组
        initGatewayRules();
        //限流异常处理
        initBlockHandler();

    }


    /**
     * 限流异常处理
     */
    private void initBlockHandler() {

        BlockRequestHandler handler = new BlockRequestHandler() {
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
                System.out.println(throwable);


                Map<Object, Object> map = new HashMap<>();
                map.put("code", "429");
                map.put("message", "接口限流了");
                map.put("data", null);
                map.put("success", false);
                return ServerResponse.status(HttpStatus.OK)
                        .contentType(MediaType.APPLICATION_JSON)
                        .body(BodyInserters.fromValue(map));
            }
        };
        GatewayCallbackManager.setBlockHandler(handler);
    }
    /**
     * 自定义限流规则Apis
     */
    private void initCustomizedApis() {
        Set<ApiDefinition> definitions = new HashSet<>();
        //把不同服务的请求进行分组
        ApiDefinition api1 = new ApiDefinition("ljq-provider-server-api")
                .setPredicateItems(new HashSet<ApiPredicateItem>() {{
                    add(new ApiPathPredicateItem().setPattern("/api/provider/**")
                            //参数值的匹配策略,目前支持精确匹配(PARAM_MATCH_STRATEGY_EXACT)、子串匹配(PARAM_MATCH_STRATEGY_CONTAINS)和正则匹配(PARAM_MATCH_STRATEGY_REGEX)
                            .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
                }});
        ApiDefinition api2 = new ApiDefinition("ljq-consumers-server-api")
                .setPredicateItems(new HashSet<ApiPredicateItem>() {{
                    add(new ApiPathPredicateItem().setPattern("/api/consumers/**")
                            .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
                }});
        ApiDefinition api3 = new ApiDefinition("ljq-gateway-api")
                .setPredicateItems(new HashSet<ApiPredicateItem>() {{
                    add(new ApiPathPredicateItem().setPattern("/api/login/**")
                            .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
                }});
        definitions.add(api1);
        definitions.add(api2);
        definitions.add(api3);
        //手动加载
        GatewayApiDefinitionManager.loadApiDefinitions(definitions);
    }

    /**
     * 初始化网关规则
     * GatewayFlowRule:网关限流规则,针对 API Gateway 的场景定制的限流规则,可以针对不同 route 或自定义的 API 分组进行限流,支持针对请求中的参数、Header、来源 IP 等进行定制化的限流。
     * resource:资源名称,可以是网关中的 route 名称或者用户自定义的API 分组名称。
     * resourceMode:规则是针对 API Gateway 的route(RESOURCE_MODE_ROUTE_ID)还是用户在 Sentinel 中定义的API 分组(RESOURCE_MODE_CUSTOM_API_NAME),默认是route。
     * grade:限流指标维度,同限流规则的grade 字段。
     * count:限流阈值
     * intervalSec:统计时间窗口,单位是秒,默认是1 秒(目前仅对参数限流生效)。
     * controlBehavior:流量整形的控制效果,同限流规则的 controlBehavior 字段,目前支持快速失败和匀速排队两种模式,默认是快速失败。
     * burst:应对突发请求时额外允许的请求数目(目前仅对参数限流生效)。
     * maxQueueingTimeoutMs:匀速排队模式下的最长排队时间,单位是毫秒,仅在匀速排队模式下生效。
     * paramItem:参数限流配置。若不提供,则代表不针对参数进行限流,该网关规则将会被转换成普通流控规则;否则会转换成热点规则。其中的字段:
     * parseStrategy:从请求中提取参数的策略,目前支持提取来源 IP(PARAM_PARSE_STRATEGY_CLIENT_IP)、Host(PARAM_PARSE_STRATEGY_HOST)、任意 Header(PARAM_PARSE_STRATEGY_HEADER)和任意 URL 参数(PARAM_PARSE_STRATEGY_URL_PARAM)四种模式。
     * fieldName:若提取策略选择 Header 模式或 URL 参数模式,则需要指定对应的 header 名称或 URL 参数名称。
     * pattern 和 matchStrategy:为后续参数匹配特性预留,目前未实现。
     * 用户可以通过 GatewayRuleManager.loadRules(rules)手动加载网关规则,或通过 GatewayRuleManager.register2Property(property)注册动态规则源动态推送(推荐方式)。
     * 自定义route纬度:
     */
    private void initGatewayRules() {
        Set<GatewayFlowRule> rules = new HashSet<>();
        rules.add(new GatewayFlowRule("ljq-provider-server-api")
                .setCount(1) //限流阈值
                .setIntervalSec(1) //统计时间窗口,单位是秒,默认是1 秒(目前仅对参数限流生效)。
                .setBurst(2) //应对突发请求时额外允许的请求数目(目前仅对参数限流生效)。
        );
        rules.add(new GatewayFlowRule("ljq-consumers-server-api")
                .setCount(1) //限流阈值
                .setIntervalSec(1) //统计时间窗口,单位是秒,默认是1 秒(目前仅对参数限流生效)。
                .setBurst(2) //应对突发请求时额外允许的请求数目(目前仅对参数限流生效)。
        );
        rules.add(new GatewayFlowRule("ljq-gateway-api")
                .setCount(1)
                .setIntervalSec(1)
                .setBurst(2) //应对突发请求时额外允许的请求数目(目前仅对参数限流生效)。
        );
        //加载路由规则
        GatewayRuleManager.loadRules(rules);
    }
}

五:创建测试接口

package com.ljq.gateway.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/api")
@RestController
public class TestController {
   
   @SentinelResource(value = "login")
   @GetMapping("/login")
   public String fun(){
       System.out.println("testD 测试RT");
       return "登录成功!!!";
   }
}

六:创建启动类即可.

注意事项:
1:限流规则参考官网:

  https://sentinelguard.io/zh-cn/index.html

2: 2.1:nacos-win启动命令:

startup.cmd -m standalone

2.2:nacos-linux启动命令:

startup.sh -m standalone

2.3:账号:nacos 密码:nacos在这里插入图片描述
3:3.1:sentinel win启动:

java -Dserver.port=40008 -Dcsp.sentinel.dashboard.server=localhost:40008 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar

3.2:sentinel linux启动:

nohup java -Dserver.port=40008 -Dcsp.sentinel.dashboard.server=localhost:40008 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar >sentinel.log &

3.3:账号:sentinel 密码:sentinel在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值