alibaba / Sentinel

A powerful flow control component enabling reliability, resilience and monitoring for microservices. (面向云原生微服务的高可用流控防护组件)
https://sentinelguard.io/
Apache License 2.0
22.33k stars 8.01k forks source link

spring cloud gateway 集成 sentinel,自定义 BlockHandler 未生效 #2765

Open Maybe12131 opened 2 years ago

Maybe12131 commented 2 years ago

依赖 spring-cloud-starter-alibaba-sentinel、sentinel-spring-cloud-gateway-adapter 版本 1.8.1

自定义限流处理类

public class MySentinelBlockRequestHandler 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)
                .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;
    }
}

配置类:

@Configuration
public class SentinelGatewayAutoConfiguration implements CommandLineRunner {
    private final List<ViewResolver> viewResolvers;
    private final ServerCodecConfigurer serverCodecConfigurer;

    public SentinelGatewayAutoConfiguration(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();
    }

    @Override
    public void run(String... args) {
        GatewayCallbackManager.setBlockHandler(new MySentinelBlockRequestHandler());
    }
}
yangsir666 commented 6 days ago

怎么解决啊啊啊 啊啊啊啊