Gateway—整合sentinel流控降级详细配置

710 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第15天,点击查看活动详情

一、GateWay整合sentinel流控降级详细配置

GateWay整合sentinel的流控降级略有不同,下面就对配置进行配置讲解一下。

1-2、流控配置

1-2-1、间隔配置

以QPS为例,设置对应间隔,就是间隔n秒内允许n个QPS通过。如下为每秒2个QPS image.png

1-2-2、Burst size宽容次数设置

Burst size,就是在设置对应规则之下还允许宽容请求的次数,如下为每秒4次QPS(阈值+Burst size) image.png

1-2-3、针对请求属性设置

勾选针对请求属性,之后就可以对ip、host、header、url参数、cookie进行相关设置

1-2-3-1、Client IP

选择client ip,就可以通过精确、子串(模糊匹配)、正则对IP进行设置,如下: image.png 通过以上设置,就只针对127.0.0.1进行QPS的流控限制,其他IP访问就不进行流控设置。

1-2-3-2、Header

选择Header 之后,就可以配置Header的名称,这样就可以针对Header名称进行流控设置 image.png 通过以上配置,只有Header中包含x-request-id并且值为123。每秒请求2次就被流控。

1-2-3-3、Url参数

选择URL参数之后,就可以配置参数名称,这样就可以针对某个参数名称进行流控设置 image.png 通过以上配置,只要url中参数name为jony,那么每秒请求2次就会被流控。

1-2-3-4、Cookie

选择cookie之后,就可以配置cookie名称,这样就可以针对某个cookie名称进行流控设置 image.png 通过以上配置,只要cookie中的参数token为aaa,那么每秒请求2次就会被流控。

1-2-4、API管理流控

通过GateWay整合sentinel服务之后,就可以对服务进行流控设置,一般情况下GateWay会对多个服务进行配置。为了方便对各个服务接口流控的管理,就可以在API管理里面进行配置

1-2-4-1、设置分组API

通过新增api管理,创建新的api管理,输入api名称,下面可以增加对应的要参与流控的接口地址

image.png

新增之后,就可以看到刚刚创建好的api分组中的接口信息

image.png

1-2-4-2、给分组设置流控规则

API类型选择API分组,API名称选择刚刚创建好的分组名称 image.png

通过以上配置,只要在API分组中的接口,每秒访问超过2个QPS就会被流控。

1-2-5、降级设置

降级设置和之前设置是一样的,如下: image.png

如上配置,统计2秒内至少请求2次有1此请求异常就熔断10秒。

1-3、统一异常处理

在上面测试流控降级的时候,可以看到页面直接返回了流控降级的错误信息,这是非常不友好的,因此就需要对流控降级的异常进行统一处理,这样在后面也方便和前端同学进行对接。

1-3-1、通过代码的方式实现

新增异常处理自动配置类

@Configuration
public class GatewayConfig {
    @PostConstruct
    public void init(){
        BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable e) {
                Result r = null;
                if (e instanceof FlowException) {
                    r = Result.error(100,"接口限流了");

                } else if (e instanceof DegradeException) {
                    r = Result.error(101,"服务降级了");

                } else if (e instanceof ParamFlowException) {
                    r = Result.error(102,"热点参数限流了");

                } else if (e instanceof SystemBlockException) {
                    r = Result.error(103,"触发系统保护规则了");

                } else if (e instanceof AuthorityException) {
                    r = Result.error(104,"授权规则不通过");
                }
                return ServerResponse.status(HttpStatus.OK)
                        .contentType(MediaType.APPLICATION_JSON)
                        .body(BodyInserters.fromValue(r));
            }
        };

        GatewayCallbackManager.setBlockHandler(blockRequestHandler);
    }
}

添加返回Result类

public class Result<T> {
    private Integer code;
    private String msg;
    private T data;

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public Result(Integer code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public Result(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public static Result error(Integer code,String msg){
        return new Result(code,msg);
    }
}

访问测试,这样就可以返回我们预期的相关信息了,如下: image.png

1-3-2、通过配置文件设置

spring:cloud.sentinel.scg.fallback.mode = response 
spring.cloud.sentinel.scg.fallback.response-body = '{"code":403,"mes":"限流了"}'

1-4、通过代码设置流控规则

代码流控规则同样也需要写在自动配置类中,我们就还在上面那个配置类中进行编写

@Configuration
public class GatewayConfig {


    @PostConstruct
    public void doInit() {
        //初始化网关限流规则
        initGatewayRules();
        //自定义限流异常处理器
        initBlockRequestHandler();
    }

    private void initGatewayRules() {
        Set<GatewayFlowRule> rules = new HashSet<>();
        //resource:资源名称,可以是网关中的 route 名称或者用户自定义的 API 分组名称。
        //count:限流阈值
        //intervalSec:统计时间窗口,单位是秒,默认是 1 秒。
        rules.add(new GatewayFlowRule("order_route")
                .setCount(2)
                .setIntervalSec(1)
        );
        rules.add(new GatewayFlowRule("user_service_api")
                .setCount(2)
                .setIntervalSec(1)
        );

        // 加载网关规则
        GatewayRuleManager.loadRules(rules);
    }

    public void initBlockRequestHandler(){
        BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable e) {
                Result r = null;
                if (e instanceof FlowException) {
                    r = Result.error(100,"接口限流了");

                } else if (e instanceof DegradeException) {
                    r = Result.error(101,"服务降级了");

                } else if (e instanceof ParamFlowException) {
                    r = Result.error(102,"热点参数限流了");

                } else if (e instanceof SystemBlockException) {
                    r = Result.error(103,"触发系统保护规则了");

                } else if (e instanceof AuthorityException) {
                    r = Result.error(104,"授权规则不通过");
                }
                return ServerResponse.status(HttpStatus.OK)
                        .contentType(MediaType.APPLICATION_JSON)
                        .body(BodyInserters.fromValue(r));
            }
        };

        GatewayCallbackManager.setBlockHandler(blockRequestHandler);
    }
}

和之前不同的是,在初始化的时候,之前使用FlowRule而GateWay使用GateWayFlowRule

添加网关规则之前使用RuleManager,而GateWay使用GateWayRuleManager.

1-5、GateWay高可用部署

如果担心单台GateWay无法承担服务,就可以通过nginx负载多态GateWay对外提供服务,这样就可以完成GateWay的高可用部署 image.png

nginx配置如下: image.png