Srping cloud gateway 集成sentinel,以nacos作为datasource

最近在学习sentinel,也是需要在项目中用到,所以在此作以记录。

项目使用的是spring cloud gateway做转发,需要对某些接口进行限流。

gateway项目的pom.xml

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
    <version>1.8.0</version>
</dependency>

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
    <version>1.8.0</version>
</dependency>
<!-- spring cloud alibaba nacos discovery -->
<dependency>
     <groupId>com.alibaba.cloud</groupId>
     <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
     <version>2.1.3.RELEASE</version>
 </dependency>
 <!-- 1.3.3版本无法识别密码中有特殊字符的bug -->
 <dependency>
     <groupId>com.alibaba.nacos</groupId>
     <artifactId>nacos-client</artifactId>
     <version>1.4.2</version>
 </dependency>

GatewayConfiguration

我们项目没有使用到sentinel的dashboard ,因为如果用dashboard的话,需要考虑到可用性,必须要保证dashboard不挂掉。那就需要做集群,这个比较麻烦,所以就省略了dashboard了。
在nacos上配置规则,然后根据规则对请求的接口进行限流。

private void initCustomizedApis() {
        Set<ApiDefinition> definitions = new HashSet<>();
        ApiDefinition webpage = new ApiDefinition("webpage")
                .setPredicateItems(new HashSet<ApiPredicateItem>() {{
                    add(new ApiPathPredicateItem().setPattern("/collect/log/**")
                            .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
                }});
        definitions.add(webpage);
        GatewayApiDefinitionManager.loadApiDefinitions(definitions);
    }

这段代码是创建了一个统一拦截的规则,而对于这个规则的限流则在nacos上配置着。

package cn.yto.collect.gateway.config;

import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Value;
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 javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;

@Configuration
public class GatewayConfiguration {

    @Value("${spring.cloud.sentinel.datasource.ds.nacos.server-addr}")
    private String serverAddress;

    @Value("${spring.cloud.sentinel.datasource.ds.nacos.groupId}")
    private String groupId;
    @Value("${spring.cloud.sentinel.datasource.ds.nacos.dataId}")
    private String dataId;

    @Value("${spring.cloud.sentinel.datasource.ds.nacos.username}")
    private String username;

    @Value("${spring.cloud.sentinel.datasource.ds.nacos.password}")
    private String password;
    @Value("${spring.cloud.sentinel.datasource.ds.nacos.namespace}")
    private String namespace;

    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;
    }

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
        // Register the block exception handler for Spring Cloud Gateway.
        return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    }

	// 这里是加载限流规则的。
    private void loadRules() {
        Properties properties = new Properties();
        properties.setProperty("username", username);
        properties.setProperty("password", password);
        properties.setProperty("serverAddr", serverAddress);
        properties.setProperty("namespace", namespace);
        ReadableDataSource<String, List<FlowRule>> flowRuleDataSource =
                new NacosDataSource<>(properties, groupId, dataId,
                        source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
                }));
        FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
    }

    @Bean
    @Order(-1)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }

    private void initCustomizedApis() {
        /**
         * nacos 配置的规则, 先加载ApiDefinition,再加载resource=webpage_api
         * [
         *     {
         *         "resource": "webpage_api",
         *         "resourceMode": 0,
         *         "pattern": "/yto-collect/business-log/**",
         *         "count": 1000,
         *         "intervalSec": 1,
         *         "matchStrategy":1
         *     }
         * ]
         */
        Set<ApiDefinition> definitions = new HashSet<>();
        ApiDefinition webpage = new ApiDefinition("webpage")
                .setPredicateItems(new HashSet<ApiPredicateItem>() {{
                    add(new ApiPathPredicateItem().setPattern("/collect/log/**")
                            .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
                }});
        definitions.add(webpage);
        GatewayApiDefinitionManager.loadApiDefinitions(definitions);
    }


    @PostConstruct
    public void doInit() {
        initCustomizedApis();
        loadRules();
//        initCustomizedApis();
//        initGatewayRules();
    }
}

nacos上的配置

针对webpage这个分组,每秒1000次的限流。

[
    {
        "resource": "webpage",
        "resourceMode": 0,
        "count": 1000,
        "intervalSec": 1,
        "matchStrategy":1
    }
]

有不清楚的,可以一起交流,QQ:303579750,欢迎一起学习

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值