Spring Cloud Gateway集成Sentinel 1.8.6及Sentinel Dashboard

这篇具有很好参考价值的文章主要介绍了Spring Cloud Gateway集成Sentinel 1.8.6及Sentinel Dashboard。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、安装sentinel

1.下载地址:sentinel v1.8.6

2.启动sentinel dashboard,执行以下命令:

java -Dcsp.sentinel.log.dir=D:\xxx\sentinel\logs -Dserver.port=9217 -Dcsp.sentinel.dashboard.server=localhost:9217 -Dcsp.sentinel.heartbeat.client.ip=localhost -Dproject.name=sentinel-dashboard -Dsentinel.dashboard.auth.username=sentinel -Dsentinel.dashboard.auth.password=sentinel -jar sentinel-dashboard-1.8.6.jar

参数解释:

-Dcsp.sentinel.log.dir:日志保存路径,默认:${user.home}/logs/csp/

-Dserver.port=9217:控制台服务端口,默认:8080

-Dcsp.sentinel.dashboard.server=localhost:9217:控制台访问端口,默认:8080

-Dcsp.sentinel.heartbeat.client.ip=localhost:客户端心跳ip,多网卡需要指定这个ip,否则启动后报错,可忽略

-Dproject.name=sentinel-dashboard:控制台显示名称

-Dsentinel.dashboard.auth.username=sentinel:控制台登录账号,默认:sentinel

-Dsentinel.dashboard.auth.password=sentinel:控制台登录密码,默认:sentinel

-jar sentinel-dashboard-1.8.6.jar:运行sentinel1.8.6 jar包

3.启动成功界面

Spring Cloud Gateway集成Sentinel 1.8.6及Sentinel Dashboard

4.登录控制台,登录账号和密码默认为sentinel,启动命令可自定义登录账号和密码。

Spring Cloud Gateway集成Sentinel 1.8.6及Sentinel Dashboard

二、Gateway网关pom.xml引入sentinel组件

<!-- spring cloud gateway 核心 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
    <version>3.1.4</version>
</dependency>

<!-- spring cloud gateway sentinel 适配器-->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
    <version>1.8.6</version>
</dependency>

<!-- spring cloud gateway sentinel连接控制台,发现服务 -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-transport-simple-http</artifactId>
    <version>1.8.6</version>
</dependency>

三、注入对应的 SentinelGatewayFilter 实例以及 SentinelGatewayBlockExceptionHandler即可,参考官方文档:https://sentinelguard.io/zh-cn/docs/api-gateway-flow-control.html

@Configuration
public class GatewayConfiguration {

    private final List<ViewResolver> viewResolvers;
    private final ServerCodecConfigurer serverCodecConfigurer;

    public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,
                                ServerCodecConfigurer serverCodecConfigurer) {
        this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
        this.serverCodecConfigurer = serverCodecConfigurer;
    }

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
        // Register the block exception handler for Spring Cloud Gateway.
        return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    }

    @Bean
    @Order(-1)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }

    @PostConstruct
    public void doInit() {
        initCustomizedApis();
    }

    private void initCustomizedApis() {
        Set<ApiDefinition> definitions = new HashSet<>();
        ApiDefinition api1 = new ApiDefinition("some_customized_api")
            .setPredicateItems(new HashSet<ApiPredicateItem>() {{
                add(new ApiPathPredicateItem().setPattern("/animal/**")
                    .setMatchStrategy(SentinelGatewayConstants.PARAM_MATCH_STRATEGY_PREFIX));
            }});
        ApiDefinition api2 = new ApiDefinition("another_customized_api")
            .setPredicateItems(new HashSet<ApiPredicateItem>() {{
                add(new ApiPathPredicateItem().setPattern("/system/**"));
            }});
        definitions.add(api1);
        definitions.add(api2);
        GatewayApiDefinitionManager.loadApiDefinitions(definitions);
    }

private void initGatewayRules() {
        Set<GatewayFlowRule> rules = new HashSet<>();
        rules.add(new GatewayFlowRule("system-route")
                .setCount(1) // 限流阈值
                .setIntervalSec(1)); // 统计时间窗口,单位是秒,默认是 1 秒

        rules.add(new GatewayFlowRule("animal-route")
                .setCount(1) // 限流阈值
                .setIntervalSec(1)); // 统计时间窗口,单位是秒,默认是 1 秒
        GatewayRuleManager.loadRules(rules);
    }
}

四、application.yaml配置路由

server:
  port: 9211
spring:
  application:
    name: spring-cloud-gateway
  cloud:
    gateway:
      routes:
        # Add your routes here.
        - id: system_route
          uri: lb://system
          predicates:
            - Path=/system/**
        - id: animal_route
          uri: lb://animal
          predicates:
            - Path=/animal/**

五、启动网关Gateway、服务,触发限流

Spring Cloud Gateway集成Sentinel 1.8.6及Sentinel Dashboard

正常访问

Spring Cloud Gateway集成Sentinel 1.8.6及Sentinel Dashboard

触发限流

六、嗯哼?sentinel dashboard没有显示嘛,怎么回事?

Spring Cloud Gateway集成Sentinel 1.8.6及Sentinel Dashboard

按官方文档说明,启动配置VM参数增加:

# 注:通过 Spring Cloud Alibaba Sentinel 自动接入的 API Gateway 整合则无需此参数

-Dcsp.sentinel.app.type=1

Spring Cloud Gateway集成Sentinel 1.8.6及Sentinel Dashboard

但是!!!好像也不行!!还必须增加一个参数,指向控制台地址:

-Dcsp.sentinel.dashboard.server=localhost:9001

注意:对网关发起请求后,需要等待大概10秒左右,才会在sentinel dashboard看到网关流控控制面板。

七、小小完善

1.第六节说到,需要增加启动配置,这里有4种解决方案。

方案一,启动类Application增加以下参数:

System.setProperty(SentinelConfig.APP_TYPE_PROP_KEY, "1");

System.setProperty("csp.sentinel.dashboard.server","localhost:9001");

System.setProperty(SentinelConfig.PROJECT_NAME_PROP_KEY,"gateway-dashboard");

方案二,启动配置VM增加如下参数:

-Dcsp.sentinel.app.type=1 -Dcsp.sentinel.dashboard.server=localhost:9001 -Dproject.name=gateway-dashboard

方案三,新增sentinel.properties配置文件,详情参阅com.alibaba.csp.sentinel.config.SentinelConfigLoader加载配置逻辑,配置内容如下:

project.name=gateway-dashboard # 控制台显示名称

csp.sentinel.app.type=1 # 指定类型为gateway网关类型

csp.sentinel.dashboard.server=localhost:9211 # 指定sentinel dashboard控制台地址

方案四,application.yaml增加自定义配置参数,再参照方案一

1.自定义限流全局异常

新增异常回调:

package com.akim.cloud.gateway.common.sentinel.handler;

import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebExceptionHandler;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

public class SentinelFallbackHandler implements WebExceptionHandler {
    private Mono<Void> writeResponse(ServerResponse response, ServerWebExchange exchange) {
        ServerHttpResponse serverHttpResponse = exchange.getResponse();
        serverHttpResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        byte[] datas = "{'code':429, 'msg':'系统繁忙,请稍后再试!'}".getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = serverHttpResponse.bufferFactory().wrap(datas);
        return serverHttpResponse.writeWith(Mono.just(buffer));
    }

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        if (exchange.getResponse().isCommitted()) {
            return Mono.error(ex);
        }
        if (!BlockException.isBlockException(ex)) {
            return Mono.error(ex);
        }
        return handleBlockedRequest(exchange, ex).flatMap(response -> writeResponse(response, exchange));
    }

    private Mono<ServerResponse> handleBlockedRequest(ServerWebExchange exchange, Throwable throwable) {
        return GatewayCallbackManager.getBlockHandler().handleRequest(exchange, throwable);
    }
}

2.改造GatewayConfiguration

可以看出上面配置api限流和服务分组时,很不友好,直接读取application.yaml gateway配置的routes。

新增application.yaml自定义配置:

akim:
  # gateway网关限流
  sentinel:
    enabled: true # 是否开启网关限流,默认true
    count: 10 # 限流阈值,Double类型
    intervalSec: 1 # 统计时间窗口,单位:秒,Long类型,默认1秒

新增配置文件对象类SentinelProperties.java:

package com.akim.cloud.gateway.common.sentinel.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

import javax.validation.constraints.NotNull;

@Data
@ConfigurationProperties("akim.sentinel")
public class SentinelProperties {
    @NotNull(message = "限流阈值")
    private Double count;

    @NotNull(message = "统计时间窗口,单位:秒")
    private Long intervalSec;
}

b.注入全局异常拦截

c.直接上代码

package com.akim.cloud.gateway.common.sentinel.handler;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.akim.cloud.gateway.common.sentinel.config.SentinelProperties;
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.exception.SentinelGatewayBlockExceptionHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
import org.springframework.cloud.gateway.support.NameUtils;
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.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.result.view.ViewResolver;

import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@EnableConfigurationProperties(SentinelProperties.class)
@ConditionalOnProperty(prefix = "akim.sentinel", name = "enabled", matchIfMissing = true) // 如果配置文件属性值为false,则不注入
@Configuration
@Slf4j
public class GatewayConfiguration {
    private final List<ViewResolver> viewResolvers;
    private final ServerCodecConfigurer serverCodecConfigurer;
    protected final RouteDefinitionLocator routeDefinitionLocator;
    private final SentinelProperties sentinelProperties;

    public SentinelBlockHandler(ObjectProvider<List<ViewResolver>> viewResolversProvider,
                                ServerCodecConfigurer serverCodecConfigurer,
                                RouteDefinitionLocator routeDefinitionLocator, SentinelProperties sentinelProperties) {
        this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
        this.serverCodecConfigurer = serverCodecConfigurer;
        this.routeDefinitionLocator = routeDefinitionLocator;
        this.sentinelProperties = sentinelProperties;
    }

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelFallbackHandler sentinelGatewayExceptionHandler() {
        return new SentinelFallbackHandler();
    }

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
        // Register the block exception handler for Spring Cloud Gateway.
        return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    }

    @Bean
    @Order(-1)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }

    @PostConstruct
    public void doInit() {
        // 限流api
        initCustomizedApis();
        // 服务分组流控
        initGatewayRules();
    }

    private void initCustomizedApis() {
        Set<ApiDefinition> definitions = new HashSet<>();
        List<RouteDefinition> routeDefinitions = routeDefinitionLocator.getRouteDefinitions().collectList().block();
        routeDefinitions.stream().forEach(route -> {
            PredicateDefinition pathDefinition = CollUtil.findOne(route.getPredicates(),
                    predicateDefinition -> "Path".equals(predicateDefinition.getName()));
            if (pathDefinition == null) {
                log.info("[sentinel][Route({}) 没有 Path 条件,忽略接口限流]", route.getId());
                return;
            }
            String path = pathDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0");
            if (StrUtil.isEmpty(path)) {
                log.info("[sentinel][Route({}) Path 的值为空,忽略接口限流]", route.getId());
                return;
            }
            definitions.add(new ApiDefinition(route.getId() + "-api")
                    .setPredicateItems(new HashSet<ApiPredicateItem>() {
                        {
                            // 匹配 Path 前缀以及其子路径的所有请求
                            add(new ApiPathPredicateItem().setPattern(path)
                                    .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX)); // 匹配前缀,不设置则认为完全匹配
                        }
                    }));
        });
        GatewayApiDefinitionManager.loadApiDefinitions(definitions);
    }

    /**
     * 网关限流规则
     * GatewayFlowRule参数:
     * 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: 为后续参数匹配特性预留,目前末实现。
     */
    private void initGatewayRules() {
        Set<GatewayFlowRule> rules = new HashSet<>();
        List<RouteDefinition> definitions = routeDefinitionLocator.getRouteDefinitions().collectList().block();
        definitions.stream().forEach(route -> {
            if (StrUtil.isEmpty(route.getId())) {
                log.info("[sentinel][Route 没有 Id 条件,忽略接口限流]");
                return;
            }
            rules.add(new GatewayFlowRule(route.getId())
                    .setCount(sentinelProperties.getCount()) // 限流阈值
                    .setIntervalSec(sentinelProperties.getIntervalSec())); // 统计时间窗口,单位是秒,默认是 1 秒
        });
        // 加载网关限流规则
        GatewayRuleManager.loadRules(rules);
    }
}

搞定!文章来源地址https://www.toymoban.com/news/detail-505753.html

到了这里,关于Spring Cloud Gateway集成Sentinel 1.8.6及Sentinel Dashboard的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【SpringCloud】11、Spring Cloud Gateway使用Sentinel实现服务限流

    1、关于 Sentinel Sentinel 是阿里巴巴开源的一个流量防卫防护组件,可以为微服务架构提供强大的流量防卫能力,包括流量控制、熔断降级等功能。Spring Cloud Gateway 与 Sentinel 结合,可以实现强大的限流功能。 Sentinel 具有以下特性: 丰富的应用场景:Sentinel 承接了阿里巴巴近

    2024年02月01日
    浏览(43)
  • 微服务集成spring cloud sentinel

    目录 1. sentinel使用场景 2.  sentinel组成 3. sentinel dashboard搭建  4. sentinel客户端详细使用 4.1 引入依赖 4.2 application.properties增加dashboard注册地址 4.3 手动增加限流配置类 4.4 rest接口及service类 4.5 通过dashboard动态配置限流规则 限流、熔断、监控、动态规则配置 由两部分组成, 第一

    2024年02月11日
    浏览(30)
  • 【合集】Spring Cloud 组件——架构进化史话 & Eureka,Nacos,OpenFeign,Ribbon,Sentinel,Gateway ,Seata+事务. . .

    Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线,一次性令牌,全局锁,领导选举,分布式会话,集群状态)。 注意: 首先,尽管Spring Cloud带有“Cloud”这个单词,但它并不是云计算解

    2024年02月08日
    浏览(31)
  • Spring Cloud Gateway集成Nacos实现负载均衡

    💡Nacas可以用于实现Spring Cloud Gateway中网关动态路由功能,也可以基于Nacos来实现对后端服务的负载均衡,前者利用Nacos配置中心功能,后者利用Nacos服务注册功能。 接下来我们来看下Gateway集成Nacos实现负载均衡的架构图 一. 环境准备 1. 版本环境 Jdk: java.version1.8/java.version Spr

    2024年02月10日
    浏览(37)
  • 【合集】Spring Cloud 组件——架构进化史话 & Eureka,Nacos,Apollo,OpenFeign,Ribbon,Sentinel,Gateway ,Seata+事务. . .

    Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线,一次性令牌,全局锁,领导选举,分布式会话,集群状态)。 注意: 首先,尽管Spring Cloud带有“Cloud”这个单词,但它并不是云计算解

    2024年02月03日
    浏览(73)
  • Spring Cloud Gateway集成SpringDoc,集中管理微服务API

    Spring Cloud微服务集成SpringDoc,在Spring Cloud Gateway中统一管理微服务的API,微服务上下线时自动刷新SwaggerUi中的group组。 框架 版本 Spring Boot 3.1.5 Spring Cloud 2022.0.4 Spring Cloud Alibaba 2022.0.0.0 Spring Doc 2.2.0 Nacos Server 2.2.3 公共模块里的配置是之前文章中提到的内容,加了一个webmvc和we

    2024年04月28日
    浏览(28)
  • Spring Cloud Gateway集成Nacos作为注册中心和配置中心

    本篇文章将介绍Spring Cloud Alibaba体系下Spring Cloud Gateway的搭建,服务注册中心和分布式配置中心使用Nacos,后续将会持续更新,介绍集成Sentinel,如何做日志链路追踪,如何做全链路灰度发布设计,以及Spring Cloud Gateway的扩展等。 ​ Spring Boot,Spring Cloud,Discovery,Config等基础依

    2024年02月11日
    浏览(32)
  • Sentinel Dashboard集成Nacos

    当项目上Sentinel Dashboard做流量监控的时候,我们可以通过Sentinel控制台修改限流配置,但当我们使用Nacos作为配置中心动态配置流控规则的时候,问题就来了。 首先我们要明白,Sentinel Dashboard的配置是从机器的内存中加载的,如果使用Nacos、Apollo、Zookeeper等作为我们动态加载限

    2024年02月15日
    浏览(31)
  • 【Spring Cloud Gateway】⑥SpringBoot3.x集成SpringDoc指南

    Spring Cloud Gateway 使用 Netty 作为嵌入式服务器,并基于响应式 Spring WebFlux 。做为微服务网关,多个微服务把 API 挂在 Gateway 上,如果查看某个 API 的 Swagger 还要去各个子微服务中去查看,就很不方便,如果能在 Gateway 上直接查看各个微服务的 API 文档,会方便很多,本文以截至

    2024年02月14日
    浏览(37)
  • Spring Cloud Gateway集成Actuator的安全漏洞和解决方案

    Spring Cloud Gateway是一个基于Spring Boot2.0和Spring WebFlux的API网关,它可以将请求转发到多个微服务并对请求进行路由、过滤和修改。Spring Cloud Gateway集成Actuator后可以提供更多的监控和管理功能,但是也可能导致安全漏洞。 最近线上环境出现一起安全事件,就是由于Spring Cloud Gat

    2024年02月09日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包