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访问限流跳转页面的效果。

总结

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

相关文章

  • 浅谈Java基于Consul创建分布式锁

    浅谈Java基于Consul创建分布式锁

    这篇文章主要介绍了浅谈基于Consul创建分布式锁,Consul是HashiCorp公司推出的开源工具,用于实现分布式系统的服务发现与配置Consul是分布式的、高可用的、可横向扩展的,需要的朋友可以参考下
    2023-07-07
  • 详解设计模式中的proxy代理模式及在Java程序中的实现

    详解设计模式中的proxy代理模式及在Java程序中的实现

    代理模式主要分为静态代理和动态代理,使客户端方面的使用者通过设置的代理来操作对象,下面来详解设计模式中的proxy代理模式及在Java程序中的实现
    2016-05-05
  • Netty学习教程之Netty与Marshalling结合发送对象

    Netty学习教程之Netty与Marshalling结合发送对象

    Netty是由JBOSS提供的一个Java开源框架,之前已经给大家简单介绍了一些基础与使用,下面这篇文章主要给大家介绍了关于Netty与Marshalling结合发送对象的相关资料,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-05-05
  • 文件上传SpringBoot后端MultipartFile参数报空问题的解决办法

    文件上传SpringBoot后端MultipartFile参数报空问题的解决办法

    这篇文章主要介绍了文件上传SpringBoot后端MultipartFile参数报空问题的解决办法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • 基于字符串常用API(详解)

    基于字符串常用API(详解)

    下面小编就为大家带来一篇基于字符串常用API(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • Java RabbitMQ高级特性详细分析

    Java RabbitMQ高级特性详细分析

    为了保证消息的可靠性传输,包括投递消息的生产方能投递成功,和消息消费的消费方正确消费,RabbitMQ 提供了两个确认机制,由于消息按照流通的顺序从左到右,因此为保证可靠性,MQ必须对 Producer进行确认,Consumer 必须对 MQ 进行确认
    2022-08-08
  • 关于Java中properties文件编码问题

    关于Java中properties文件编码问题

    这篇文章主要介绍了关于Java中properties文件编码问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • java回调机制实例详解

    java回调机制实例详解

    这篇文章主要介绍了java回调机制实例详解的相关资料,需要的朋友可以参考下
    2017-05-05
  • Spring Cloud入门系列服务提供者总结

    Spring Cloud入门系列服务提供者总结

    这篇文章主要介绍了Spring Cloud入门系列之服务提供者总结,服务提供者使用Eureka Client组件创建 ,创建完成以后修改某文件,具体操作方法及实例代码跟随小编一起看看吧
    2021-06-06
  • JAVA 数据结构链表操作循环链表

    JAVA 数据结构链表操作循环链表

    这篇文章主要介绍了JAVA 数据结构链表操作循环链表的相关资料,需要的朋友可以参考下
    2016-10-10

最新评论