zuul整合sentinel实现限流
效果图
一分钟以内点击三次触发限流
Setrules=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