本文主要介绍Nacos+Sentinel+gateway 实现微服务限流


目录

一、Sentinel是什么?

二、使用步骤

1.下载Sentinel

2.集成Sentinel

3.测试Sentinel


一、Sentinel是什么?

 Sentinel是阿里开源的项目,提供了流量控制、熔断降级、系统负载保护等多个维度来保障服务之间的稳定性。

二、使用步骤

1.下载Sentinel

https://github.com/alibaba/Sentinel/releases 

打开页面找到sentinel-dashboard打头的jar文件链接点击下载,下载完成后执行

java -jar sentinel-dashboard-1.7.0.jar

打开页面http://localhost:8080

输入账号sentinel密码sentinel即可进入控制台

2.集成Sentinel

在网关处添加Sentinel依赖

   <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            <version>2.2.3.RELEASE</version    
    </dependency>
  <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
            <version>1.8.0</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
            <version>1.8.5</version>
        </dependency>

在网关处添加如下配置

spring
  cloud
    sentinel:
      eager: true #这里配置true表示服务启动则与sentinel建立连接,否则需要有网关url请求才能在sentinel看到数据
      transport:
        port: 8850  
        dashboard: l27.0.0.1:8080
      datasource:
        flow-ds: #sentinel从nacos获取指定的流控规则 这个名字可以自定义,不重复就可以
          nacos:
            server-addr: 127.0.0.1:8848
            dataId: flow-server
            groupId: DEFAULT_GROUP
            ruleType: flow # flow代表流量控制,degrade代表熔断规则

添加异常处理


import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.result.view.ViewResolver;

import java.util.Collections;
import java.util.List;


@Configuration
public class GatewayConfiguration {
    private final List<ViewResolver> viewResolvers;
    private final ServerCodecConfigurer serverCodecConfigurer;

    public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer) {
        this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
        this.serverCodecConfigurer = serverCodecConfigurer;
    }
    /**
     * 初始化一个限流的过滤器
     *
     * @return
     */
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }

    /**
     * 配置限流的异常处理器
     *
     * @return
     */
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelFallbackHandler sentinelFallbackHandler() {
        return new SentinelFallbackHandler();
    }


}


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.HttpStatus;
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;

/**
 * 自定义限流异常处理
 */
public class SentinelFallbackHandler implements WebExceptionHandler
{
    private Mono<Void> writeResponse(ServerResponse response, ServerWebExchange exchange)
    {
        ServerHttpResponse serverHttpResponse = exchange.getResponse();
        serverHttpResponse.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
        serverHttpResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        byte[] datas = "{\"code\": 20001,\"data\": {},\"fail\": true,\"message\": \"系统繁忙,请稍后再试\"}".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);
    }
}

nacos添加配置文件flow-server(json格式)

[{

"resource":"/api/user/verificationImg", //限流资源

resourceMode:0,规则是针对 API Gateway 的route(RESOURCE_MODE_ROUTE_ID)还是用户在 Sentinel 中定义的API 分组(RESOURCE_MODE_CUSTOM_API_NAME),默认是route。

"controlBehavior":0, //流控效果 (0:失败,1:预热,2:排队等待)

"count":2,//单机阀值

"grade":1,//阈值类型(阀值类型,0:线程数,1:QPS)

"limitApp":"default",//针对来源 (Sentinel可以针对调用者进行限流,填写微服务名,指定对哪个微服务进行限流 ,默认default(不区分来源,全部限制))

"clusterMode":false,//是否集群(false:否,true:是)

"strategy":"0"//流控模式(0:直接,1:关联,2:链路)

}]

3.测试

启动网关即可在控制台看到naco配置的流控规则

F5快速刷新http://127.0.0.1:8891/api/user/verificationImg

出现如下json串即限流成功

{"code": 20001,"data": {},"fail": true,"message": "系统繁忙,请稍后再试"}

并能在控制台看到当前并发的QPS


Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐