1 创建工程导入依赖
spring_cloud_sentinel_demo
org.example
1.0-SNAPSHOT
4.0.0
api_gateway_server
org.springframework.cloud
spring-cloud-starter-gateway
2 配置启动类
package xx.study.sc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GatewayServerApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayServerApplication.class,args);
}
}
3编写配置文件
server.port=8080
spring.application.name=api-gateway-server
#路由配置 SpringCloud Gateway
#路由id 路由到微服务的uri 断言(判断条件)
spring.cloud.gateway.routes[0].id=product-service
spring.cloud.gateway.routes[0].uri=http://127.0.0.1:9001
spring.cloud.gateway.routes[0].predicates[0]=Path=/product/**
application.yml
1 引入Eureka依赖
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
2 修改配置文件
server.port=8080
spring.application.name=api-gateway-server
#路由配置 SpringCloud Gateway
#路由id 路由到微服务的uri 断言(判断条件)
spring.cloud.gateway.routes[0].id=product-service
#spring.cloud.gateway.routes[0].uri=http://127.0.0.1:9001
#lb:// 根据微服务名称从注册中心拉取服务请求路径
spring.cloud.gateway.routes[0].uri=lb://service-product
spring.cloud.gateway.routes[0].predicates[0]=Path=/product/**
#注册中心访问地址
eureka.client.service-url.defaultZone=http://localhost:8000/eureka/
#配置路由过滤器 将product-service/ 替换掉
spring.cloud.gateway.routes[0].predicates[0]=Path=/product-service/**
spring.cloud.gateway.routes[0].filters[0]=RewritePath=/product-service/(?.*),/${segment}
#配置 自动根据微服务名称进行路由转发
spring.cloud.gateway.discovery.locator.enabled=true
#服务名称小写呈现
spring.cloud.gateway.discovery.locator.lower-case-service-id=true
1 过滤器的生命周期
2 过滤器类型
自定义一个全局过滤器
package xx.study.sc.filter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* 定义一个全局过滤器
* 实现 GlobalFilter, Ordered接口
*/
@Component
public class LoginFilter implements GlobalFilter, Ordered {
/**
* 执行过滤器中的业务逻辑
* @param exchange
* @param chain
* @return
*/
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("执行自定义全局过滤器!!!");
return chain.filter(exchange);//继续执行
}
/**
* 指定过滤器的执行顺序 值越小优先级越高
* @return
*/
public int getOrder() {
return 1;
}
}
package xx.study.sc.filter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* 定义一个全局过滤器
* 实现 GlobalFilter, Ordered接口
*/
@Component
public class LoginFilter implements GlobalFilter, Ordered {
/**
* 执行过滤器中的业务逻辑
* 对请求参数中的acces-token 进行判断
* ServerWebExchange 相当于请求响应的上下文(zuul中的RequestContext)
* @param exchange
* @param chain
* @return
*/
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("执行自定义全局过滤器!!!");
String token=exchange.getRequest().getQueryParams().getFirst("access-token");
if (token==null){
System.out.println("m没有登录");
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
//如果存在继续执行
return chain.filter(exchange);//继续执行
}
/**
* 指定过滤器的执行顺序 值越小优先级越高
* @return
*/
public int getOrder() {
return 1;
}
}
1 计数器
2 漏桶算法
3 令牌桶算法
1 准备工作
redis
在工程引入redis依赖
org.springframework.boot
spring-boot-starter-actuator
org.springframework.boot
spring-boot-starter-data-redis-reactive
2 修改网关中的application.properties
server.port=8080
spring.application.name=api-gateway-server
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.database=0
#配置 自动根据微服务名称进行路由转发
spring.cloud.gateway.discovery.locator.enabled=true
#服务名称小写呈现
spring.cloud.gateway.discovery.locator.lower-case-service-id=true
#注册中心访问地址
eureka.client.service-url.defaultZone=http://localhost:8000/eureka/
application.properties 不知怎么来配置,故在application,yml进行配置(后续再补上)
spring:
cloud:
gateway:
routes:
- id: product-service
uri: lb://service-product
predicates:
- Path=/product-service/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 1
redis-rate-limiter.burstCapacity: 1
key-resolver: "#{@userKeyResolver}"
- RewritePath=/product-service/(?.*),/${segment}
3 配置redis中key的解析器keySesolver
package xx.study.sc.filter;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Configuration
public class KeyResolverConfiguration {
/**
* 编写基于请求路径的限流规则
* //abc
* //基于请求ip
* //基于参数
* @return
*/
// @Bean
public KeyResolver pathKeyResolver(){
//自定义KeyResolver
return new KeyResolver() {
/**
* 上下文参数
* @param exchange
* @return
*/
public Mono resolve(ServerWebExchange exchange) {
return Mono.just(exchange.getRequest().getPath().toString());
}
};
}
/**
* 基于请求参数
* ?userId=make
* @return
*/
@Bean
public KeyResolver userKeyResolver(){
return exchange -> Mono.just(
exchange.getRequest().getQueryParams().getFirst("userId")
// exchange.getRequest().getHeaders().getFirst("X-Forwarded-For")//基于ip的限流
);
}
}
redis 客户端可以监控状态
1 引入依赖
com.alibaba.csp
sentinel-spring-cloud-gateway-adapter
1.6.0
2 配置类实现
package xx.study.sc.config;
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.sc.SentinelGatewayFilter;
import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.result.view.ViewResolver;
import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Configuration
public class GatewayConfiguration {
private final List viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;
public GatewayConfiguration(ObjectProvider> viewResolversProvider,
ServerCodecConfigurer serverCodecConfigurer) {
this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
this.serverCodecConfigurer = serverCodecConfigurer;
}
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
// Register the block exception handler for Spring Cloud Gateway.
return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
}
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public GlobalFilter sentinelGatewayFilter() {
return new SentinelGatewayFilter();
}
@PostConstruct
public void doInit() {
initGatewayRules();
}
/**
* 配置限流规则
*/
private void initGatewayRules() {
Set rules = new HashSet<>();
rules.add(new GatewayFlowRule("product-service")
.setCount(1) // 限流阈值
.setIntervalSec(1) // 统计时间窗口,单位是秒,默认是 1 秒
);
GatewayRuleManager.loadRules(rules);
}
}
注意增加规则