Sentinel Gateway自定义限流返回结果方式

 更新时间:2025年04月02日 09:46:16   作者:Dust-Tyh  
这篇文章主要介绍了Sentinel Gateway自定义限流返回结果方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

Sentinel Gateway自定义限流返回结果

sentinel在1.6.0后就引入了Sentinel API Gateway Adapter Common,适配了Gateway。

以前sentinel自定义限流结果是通过实现BlockExceptionHandler接口进行自定义限流返回结果,但是如果是使用了spring-cloud-alibaba-sentinel-gateway的依赖进行限流的话,使用之前的接口是不起作用的。

首先是我本地项目的环境,适配的是springboot 2.3.12.RELEASE版本,cloud版本为Hoxton.SR12。

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            <version>2.2.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
            <version>2.2.7.RELEASE</version>
        </dependency>

通过SentinelSCGAutoConfiguration配置类,我们可以看到主要有两种方法可以实现自定义:配置文件配置和自定义代码配置。

1、配置文件配置

在application.yml加入以下配置:

spring:
  cloud:
    sentinel:
      scg:
        fallback:
          mode: response
          responseBody: "{\"code\":\"429\",\"msg\":\"请求太多了\"}"

对应的配置类为FallbackProperties,以下是详细的配置:

	/**
	 * The fallback mode for sentinel spring-cloud-gateway. choose `redirect` or
	 * `response`.
	 */
	private String mode;

	/**
	 * Redirect Url for `redirect` mode.
	 */
	private String redirect;

	/**
	 * Response Body for `response` mode.
	 */
	private String responseBody;

	/**
	 * Response Status for `response` mode.
	 */
	private Integer responseStatus = HttpStatus.TOO_MANY_REQUESTS.value();

	/**
	 * Content-Type for `response` mode.
	 */
	private String contentType = MediaType.APPLICATION_JSON.toString();

可以通过配置看到根据mode的类型处理模式有两种:responseredirect。在SentinelSCGAutoConfiguration中对应的代码在 initFallback() 方法。

  • response

如果设置mode为response则返回contentType 类型的responseBody,响应码为responseStatus 。

  • redirect

如果设置mode为redirect,则限流后自动跳转某个页面,页面地址为redirect。

2、自定义代码配置

通过Sentinel wiki 我们可以看到:

所以我们可以通

GatewayCallbackManagersetBlockHandler() 方法来实现注册我们自定义的异常处理类,需要实现BlockRequestHandler接口,默认的异常处理类是:DefaultBlockRequestHandler

首先自定义一个异常处理类:

import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.InvalidMediaTypeException;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.util.List;

import static org.springframework.web.reactive.function.BodyInserters.fromValue;

/**
 * @author TYH
 * @Description: Sentinel异常处理类
 * @date 2022/3/8 14:34
 */
public class SentinelBlockRequestHandler implements BlockRequestHandler {

    @Override
    public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable t) {
        // 判断是否是html访问,如果是则转发url
        if (acceptsHtml(exchange)) {
            return htmlErrorResponse();
        }
        // 如果是接口访问,则返回提示
        return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS)
                .contentType(MediaType.APPLICATION_JSON_UTF8)
                .body(fromValue(new ResponseData(HttpStatus.TOO_MANY_REQUESTS.value(),"请求太多了")));
    }

    private Mono<ServerResponse> htmlErrorResponse() {
        String url="http://www.baidu.com";
        URI uri =URI.create(url);
        return ServerResponse.temporaryRedirect(uri).build();
    }

    private boolean acceptsHtml(ServerWebExchange exchange) {
        try {
            List<MediaType> acceptedMediaTypes = exchange.getRequest().getHeaders().getAccept();
            acceptedMediaTypes.remove(MediaType.ALL);
            MediaType.sortBySpecificityAndQuality(acceptedMediaTypes);
            return acceptedMediaTypes.stream()
                    .anyMatch(MediaType.TEXT_HTML::isCompatibleWith);
        } catch (InvalidMediaTypeException ex) {
            return false;
        }
    }

    /**
     * 定义返回的实体类,字段根据需要添加
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    static class ResponseData {
        private int code;
        private String msg;
    }
}

然后再调用GatewayCallbackManager的方法进行注册:

import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Configuration;

/**
 * @author TYH
 * @Description:
 * @date 2022/3/8 15:02
 */
@Slf4j
@Configuration
public class InitConfig implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        log.info("初始化限流handler");
        GatewayCallbackManager.setBlockHandler(new SentinelBlockRequestHandler());
    }
}

然后就实现了接口访问限流返回固定值,html访问限流跳转页面的效果。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 关于SpringBoot单元测试(cobertura生成覆盖率报告)

    关于SpringBoot单元测试(cobertura生成覆盖率报告)

    这篇文章主要介绍了关于SpringBoot单元测试(cobertura生成覆盖率报告),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • Ajax登录验证实现代码

    Ajax登录验证实现代码

    这篇文章主要为大家详细介绍了jQuery+ajax实现用户登录验证,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • Mybatis-Plus查询中如何排除标识字段

    Mybatis-Plus查询中如何排除标识字段

    这篇文章主要介绍了Mybatis-Plus查询中排除标识字段的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • 聊聊单线程的Redis为何会快到飞起

    聊聊单线程的Redis为何会快到飞起

    Redis想必大家都或多或少听过吧,我们在工作学习中通常用它来作为缓存使用,既然是作为缓存,大家的第一反应肯定是:这家伙很快
    2022-02-02
  • IKAnalyzer结合Lucene实现中文分词(示例讲解)

    IKAnalyzer结合Lucene实现中文分词(示例讲解)

    下面小编就为大家带来一篇IKAnalyzer结合Lucene实现中文分词(示例讲解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • SpringBoot详细分析自动装配原理并实现starter

    SpringBoot详细分析自动装配原理并实现starter

    相对于传统意义上的Spring项目,SpringBoot具有开箱即用,简化配置,内置Tomcat等等等等一系列的特点。在这些特点中,最重要的两条就是约定优于配置和自动装配
    2022-07-07
  • spring源码学习之bean的初始化以及循环引用

    spring源码学习之bean的初始化以及循环引用

    这篇文章主要给大家介绍了关于spring源码学习之bean的初始化以及循环引用的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • 将Mybatis升级为Mybatis-Plus的详细过程

    将Mybatis升级为Mybatis-Plus的详细过程

    本文详细介绍了在若依管理系统(v3.8.8)中将MyBatis升级为MyBatis-Plus的过程,旨在提升开发效率,通过本文,开发者可实现系统功能无损升级,同时享受MyBatis-Plus带来的便捷特性,如代码简化和性能优化,需要的朋友可以参考下
    2025-04-04
  • Spring security实现权限管理示例

    Spring security实现权限管理示例

    这篇文章主要介绍了Spring security实现权限管理示例,这里整理了详细的代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-01-01
  • 关于IO密集型服务提升性能的三种方式

    关于IO密集型服务提升性能的三种方式

    这篇文章主要介绍了关于IO密集型服务提升性能的三种方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07

最新评论