zuul整合ratelimit实现限流


正常调用结果

 触发限流后提示

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

    
        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
            
        
    



  zuul网关配置

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

    
        zuul-aprent
        org.example
        1.0-SNAPSHOT
    
    4.0.0

    com.zuul
    zuul-two

    
        
        
            org.springframework.cloud
            spring-cloud-starter-netflix-zuul
        
        
        
            org.projectlombok
            lombok
            1.18.16
        
        
        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-client
        


        
            com.marcosbarbero.cloud
            spring-cloud-zuul-ratelimit
            2.2.5.RELEASE
        

        
            org.springframework.boot
            spring-boot-starter-data-redis
        

        
            com.google.code.gson
            gson
            2.8.6
        

    

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



server.port=1004

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


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




#开启限流保护
zuul.ratelimit.enabled=true

#限流数据存储方式
zuul.ratelimit.repository=redis

#自定义需要被限流的服务名
zuul.ratelimit.policy-list.order-service[0].limit=5
zuul.ratelimit.policy-list.order-service[0].refresh-interval=60

spring.redis.database=1
spring.redis.host=127.0.0.1
spring.redis.port=6379 
spring.redis.password=
package com.zuul;

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

/**
 * @author yourheart
 * @Description   自定义限流策略
 * @create 2022-05-21 23:44
 */
@SpringBootApplication
//开启zuul注解
@EnableZuulProxy
@EnableDiscoveryClient
public class ZuulTwoApplication {

    public static void main(String[] args) {
        SpringApplication.run(ZuulTwoApplication.class,args);
    }
}

  配置token验证

package com.zuul.config;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @author yourheart
 * @Description
 * @create 2022-05-09 21:56
 */
@Component
@Slf4j
public class AccessFilter extends ZuulFilter {
    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 1;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        //获取请求上下文
        RequestContext rc = RequestContext.getCurrentContext();
        HttpServletRequest request = rc.getRequest();
        String token=request.getHeader("token");
        if (null==token){
            log.warn("【token为空】");
            //请求结束
            rc.setSendZuulResponse(false);
            //状态码,401未授权
            rc.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
            rc.getResponse().setContentType("application/jsop; charset=utf-8");
            PrintWriter writer=null;

            try {
                writer=rc.getResponse().getWriter();
                writer.print("401,登录未授权");
            } catch (IOException e) {
                e.printStackTrace();
            }

        }else {
            log.info("【token id ok】token:{}",token);
        }

        return null;
    }
} 

自定义限流策略

package com.zuul.config;

import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.RateLimitUtils;
import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.properties.RateLimitProperties;
import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.support.DefaultRateLimitKeyGenerator;
import org.springframework.cloud.netflix.zuul.filters.Route;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * @author yourheart
 * @Description
 * @create 2022-05-21 23:46
 */
@Component
public class RateLimitKeyGenerator extends DefaultRateLimitKeyGenerator {

    public RateLimitKeyGenerator(RateLimitProperties properties, RateLimitUtils rateLimitUtils) {
        super(properties, rateLimitUtils);
    }

    /**
     * 自定义限流策略
     * @param request
     * @param route
     * @param policy
     * @return
     */
    @Override
    public String key(HttpServletRequest request, Route route, RateLimitProperties.Policy policy) {
        return super.key(request, route, policy)+":"+request.getParameter("orderId");
    }
}

  定制触发限流返回的错误信息

package com.zuul.handler;

import com.google.gson.JsonObject;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author yourheart
 * @Description
 * @create 2022-05-22 10:51
 */
@RestController
public class ExceptionHandler implements ErrorController {
    @Override
    public String getErrorPath() {
        return "error";
    }


    @RequestMapping(value="/error")
    public String error(){

        JsonObject jsonObject=new JsonObject();
        jsonObject.addProperty("code","429");
        jsonObject.addProperty("msg","已触发限流,服务不可用");
        String result = jsonObject.toString();
        return result;
    }
}
<?xml version="1.0" encoding="UTF-8"?>

    
        zuul-aprent
        org.example
        1.0-SNAPSHOT
    
    4.0.0

    com.order
    order-service

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

        
            org.springframework.cloud
            spring-cloud-starter-openfeign
        
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
        
            com.alibaba
            fastjson
            1.2.7
        

        
        
            org.projectlombok
            lombok
            1.18.16
        

    

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





package com.order;

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

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


package com.order;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
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:46
 */
@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {


    @Autowired
    private ProductService productService;

    @GetMapping("/getId")
    public String getId(Integer orderId){
        return "返回的订单号:"+orderId;
    }

    @GetMapping("/getOrder/{id}")
    public String getProduct(@PathVariable  String id){
        log.info("【调用消费者入参】:{}",id);
        String selectProduct = productService.selectProduct(id);
        return selectProduct;
    }
}


package com.order;


import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient(value = "product-service")
public interface ProductService {

    @GetMapping("/product/getProduct/{id}")
    String selectProduct(@PathVariable String id);
}
productService.selectProduct(id)该方法可以自己定义
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
    





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


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

  调用http://127.0.0.1:1004/order-service/order/getId?orderId=10

本次配置的是60秒内,调用5次触发限流

相关