zuul整合ratelimit实现限流
正常调用结果
触发限流后提示
父类pom
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | <?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> </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> |
zuul网关配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | <?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-two</artifactId> <dependencies> <!--zuul依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency> <!--lombok依赖--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version> 1.18 . 16 </version> </dependency> <!--客户端--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>com.marcosbarbero.cloud</groupId> <artifactId>spring-cloud-zuul-ratelimit</artifactId> <version> 2.2 . 5 .RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version> 2.8 . 6 </version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> <finalName>zuul</finalName> </build> </project> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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= |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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验证
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | 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 ; } } |
自定义限流策略
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 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" ); } } |
定制触发限流返回的错误信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 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; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | <?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.order</groupId> <artifactId>order-service</artifactId> <dependencies> <!--客户端--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</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> <!--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>order</finalName> </build> </project> 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项目
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | <?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> 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次触发限流
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异