zuul整合sentinel实现限流

效果图

 

 一分钟以内点击三次触发限流

Set<GatewayFlowRule> rules=new HashSet<>();
rules.add(new GatewayFlowRule("product-service").setCount(3).setIntervalSec(60));
GatewayRuleManager.loadRules(rules);

 自定义限流返回结果

 本次测试需要三个项目,eureka项目,product项目,zuul网关项目

父级pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>zuul-aprent</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>eureka-service</module>
        <module>prodoct-service</module>
        <module>order-service</module>
        <module>zuul-service</module>
        <module>zuul-one</module>
        <module>zuul-two</module>
        <module>zuul-three</module>
        <module>zuul-sentinal</module>
    </modules>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
    </parent>

    <dependencyManagement>

        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.1.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>



        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <!--编译插件-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>utf-8</encoding>
                </configuration>
            </plugin>
            <!--打包插件-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

  eureka项目

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>zuul-aprent</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.eureka</groupId>
    <artifactId>eureka-service</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
        <finalName>eureka</finalName>
    </build>


</project>

  

package com.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
 * @author yourheart
 * @Description
 * @create 2022-04-20 21:17
 */
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class,args);
    }
}

  

server.port=8761
spring.application.name=eureka-service
eureka.instance.hostname=localhost
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false

logging.level.com.eureka=info
logging.level.web=info
spring.devtools.add-properties=false

  product项目

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>zuul-aprent</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.product</groupId>
    <artifactId>prodoct-service</artifactId>

    <dependencies>
    <!--客户端-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <!--web依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--添加fastjson依赖-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.7</version>
    </dependency>
    <!--判断空的用法  -->
    <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>2.6</version>
    </dependency>
        <!--lombok依赖-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
        <finalName>product</finalName>
    </build>


</project>

  

server.port=1000

spring.application.name=product-service
#注册到eureka注册中心,如果是注册到集群就用逗号连接多个,单实例写上一个就好
eureka.client.service-url.defaultZone=http://localhost:8761/eureka


logging.level.com.product=debug
logging.level.web=debug
spring.devtools.add-properties=false

  

package com.product;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

/**
 * @author yourheart
 * @Description
 * @create 2022-04-20 21:28
 */
@SpringBootApplication
@EnableDiscoveryClient
public class ProductApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProductApplication.class,args);
    }
}


package com.product.controller.front;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author yourheart
 * @Description
 * @create 2022-04-20 21:30
 */
@RestController
@RequestMapping("/product")
@Slf4j
public class ProductController {

    @GetMapping("/getProduct/{id}")
    public String selectProduct(@PathVariable String id){
        log.info("【调用服务者入参】:{}",id);
        return "查询到的主键返回"+id;
    }


    @GetMapping("/testFirst/{id}")
    public String testFirst(@PathVariable Integer id){
        log.info("【调用服务者入参】:{}",id);

        StringBuilder stringBuilder=new StringBuilder();
        stringBuilder.append("qwe");
        stringBuilder.append("-");
        stringBuilder.append(id);
        return stringBuilder.toString();
    }
}

  zuul项目

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>zuul-aprent</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zuul</groupId>
    <artifactId>zuul-sentinal</artifactId>

    <dependencies>
        <!--spring cloud zuul依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>

        <!--netflix eureka client依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-zuul-adapter</artifactId>
            <version>1.8.2</version>
        </dependency>

    </dependencies>


</project>

  

server.port=1006

spring.application.name=zuul-sentinal
#注册到eureka注册中心,如果是注册到集群就用逗号连接多个,单实例写上一个就好
eureka.client.service-url.defaultZone=http://localhost:8761/eureka


logging.level.com.zuul=debug
logging.level.web=debug
spring.devtools.add-properties=false


#设置为不支持 URL 粒度
spring.cloud.sentinel.filter.enabled=false

  

package com.zuul;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

/**
 * @author yourheart
 * @Description
 * @create 2022-06-06 23:22
 */
@SpringBootApplication
//开启zuul注解
@EnableZuulProxy
@EnableDiscoveryClient
public class SentinalApplication {
    public static void main(String[] args) {
        SpringApplication.run(SentinalApplication.class,args);
    }
}


package com.zuul.exception;

import com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback.BlockResponse;
import com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback.DefaultBlockFallbackProvider;
import com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback.ZuulBlockFallbackProvider;
import com.alibaba.csp.sentinel.log.RecordLog;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author yourheart
 * @Description
 * @create 2022-06-09 0:19
 */
public class MyBlockFallbackProvider implements ZuulBlockFallbackProvider {

    private Logger logger = LoggerFactory.getLogger(DefaultBlockFallbackProvider.class);

    @Override
    public String getRoute() {
        return "*";
    }

    @Override
    public BlockResponse fallbackResponse(String route, Throwable cause) {
        RecordLog.info(String.format("[Sentinel DefaultBlockFallbackProvider] Run fallback route: %s", route));
        if (cause instanceof BlockException) {
            return new BlockResponse(429, "Sentinel触发限流", route);
        } else {
            return new BlockResponse(500, "系统异常", route);
        }
    }
}


package com.zuul.filter;

import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback.ZuulBlockFallbackManager;
import com.alibaba.csp.sentinel.adapter.gateway.zuul.filters.SentinelZuulErrorFilter;
import com.alibaba.csp.sentinel.adapter.gateway.zuul.filters.SentinelZuulPostFilter;
import com.alibaba.csp.sentinel.adapter.gateway.zuul.filters.SentinelZuulPreFilter;
import com.netflix.zuul.ZuulFilter;
import com.zuul.exception.MyBlockFallbackProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.Set;

/**
 * @author yourheart
 * @Description
 * @create 2022-06-06 23:30
 */
@Configuration
public class ZuulConfigFilter {

    @Bean
    public ZuulFilter sentinelZuulPreFilter(){
        return new SentinelZuulPreFilter();
    }

    @Bean
    public ZuulFilter sentinelZuulPostFilter(){
        return new SentinelZuulPostFilter();
    }

    @Bean
    public ZuulFilter sentinelZuulErrorFilter(){
        return new SentinelZuulErrorFilter();
    }

    /**
     * spring容器初始化调用该方法
     */
    @PostConstruct
    public void doInt(){
        /**
         * 注册 FallbackProvider
         */
        ZuulBlockFallbackManager.registerProvider(new MyBlockFallbackProvider());

        /**
         * 加载网关限流规则
         */
       initGatewayRules();

    }

    private void initGatewayRules(){

        Set<GatewayFlowRule> rules=new HashSet<>();
        /**
         * 设置为60秒点击3次触发限流
         */
        rules.add(new GatewayFlowRule("product-service").setCount(3).setIntervalSec(60));
        GatewayRuleManager.loadRules(rules);


    }
}

  测试地址http://127.0.0.1:1006/product-service/product/getProduct/1992

官方文档提供大家学习

https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel

https://github.com/alibaba/Sentinel/wiki/%E7%BD%91%E5%85%B3%E9%99%90%E6%B5%81

 

 

 

posted @ 2022-06-09 00:50  不忘初心2021  阅读(234)  评论(0编辑  收藏  举报