为了展示更加友好的限流提示, Sentinel
支持自定义异常处理。
# Spring
spring:
cloud:
sentinel:
scg:
fallback:
mode: response
response-body: '{"code":403,"msg":"请求超过最大数,请稍后再试"}'
这种方式比较简单,直接在配置文件中指定了限流异常时的响应体内容。当触发限流时,会返回
{"code":403,"msg":"请求超过最大数,请稍后再试"}
这样的JSON
响应。
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelFallbackHandler sentinelGatewayExceptionHandler()
{
return new SentinelFallbackHandler();
}
这种方式需要自定义
SentinelFallbackHandler
类,实现WebExceptionHandler
接口。在handle()
方法中,先判断是否为Sentinel
限流异常,如果是,则调用handleBlockedRequest()
方法获取响应,并通过writeResponse()
方法写入响应体。
package com.ruoyi.gateway.handler;
import java.nio.charset.StandardCharsets;
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;
/**
* 自定义限流异常处理
*
* @author ruoyi
*/
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);
}
}
这个实现与第一种方案的区别在于,它可以自定义更复杂的限流异常处理逻辑。例如,可以根据不同的限流规则,返回不同的响应内容。
总的来说,这两种实现方式都可以实现自定义的
Sentinel
限流异常处理,选择哪种方式取决于具体的需求。
– 如果需求比较简单,可以选择第一种基于配置文件的方式;
– 如果需求比较复杂,需要根据不同的限流规则返回不同的响应,可以选择第二种自定义SentinelFallbackHandler
的方式。
powered by kaifamiao