zuul整合sentinel实现限流


效果图

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

Set 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"?>

    4.0.0

    org.example
    zuul-aprent
    pom
    1.0-SNAPSHOT
    
        eureka-service
        prodoct-service
        order-service
        zuul-service
        zuul-one
        zuul-two
        zuul-three
        zuul-sentinal
    

    
        org.springframework.boot
        spring-boot-starter-parent
        2.2.5.RELEASE
    

    

        
            
                org.springframework.cloud
                spring-cloud-dependencies
                Hoxton.SR3
                pom
                import
            

            
                com.alibaba.cloud
                spring-cloud-alibaba-dependencies
                2.1.0.RELEASE
                pom
                import
            



        
    

    
        
            
            
                org.apache.maven.plugins
                maven-compiler-plugin
                
                    1.8
                    1.8
                    utf-8
                
            
            
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    



  eureka项目

<?xml version="1.0" encoding="UTF-8"?>

    
        zuul-aprent
        org.example
        1.0-SNAPSHOT
    
    4.0.0

    com.eureka
    eureka-service

    
        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-server
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
        eureka
    



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"?>

    
        zuul-aprent
        org.example
        1.0-SNAPSHOT
    
    4.0.0

    com.product
    prodoct-service

    
    
    
        org.springframework.cloud
        spring-cloud-starter-netflix-eureka-client
    
    
    
        org.springframework.boot
        spring-boot-starter-web
    
    
    
        com.alibaba
        fastjson
        1.2.7
    
    
    
        commons-lang
        commons-lang
        2.6
    
        
        
            org.projectlombok
            lombok
            1.18.16
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
        product
    



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"?>

    
        zuul-aprent
        org.example
        1.0-SNAPSHOT
    
    4.0.0

    com.zuul
    zuul-sentinal

    
        
        
            org.springframework.cloud
            spring-cloud-starter-netflix-zuul
        

        
        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-client
        

        
            com.alibaba.csp
            sentinel-zuul-adapter
            1.8.2
        

    



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