gateway 处了除了网关和路由功能外 还有 健权、限流、过滤等功能,如图。
如图所示:现有断言、映射,而过滤功能在最后;
一、过滤器分为全局的和局部的,官网有简介:
1、
spring:
cloud:
gateway:
routes:
- id: query_route
uri: http://localhost:8001
predicates:
- Query=green
2、全局过滤器的核心代码(8001服务中 gateway 服务):
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
//实现了全局过滤器的 filter 接口,做服务过滤转发
public class ShadowGlobaFilter implements GlobalFilter , Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
MultiValueMap<String, HttpCookie> cookies = request.getCookies();
for (String s : cookies.keySet()) {
if(s.equals("x")){
System.out.println("----------------------");
return chain.filter(exchange);
}
}
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
}
//过滤器的执行顺序,值越小,执行优先级越高
@Override
public int getOrder() {
return 0;
}
}
如果8000是gateway 服务,核心配置如下:首先保证所有请求都能进来;如果非gateway 服务,则无需这样配置。
server:
port: 8001
spring:
application:
name: register-gateway-8001
cloud:
gateway:
#gateway的服务发现
discovery:
locator:
# 根据注册中心自动注册路由,默认false 重启生效
enabled: true
#开始小写转换,重启生效
lowerCaseServiceId: true
# 跨域配置
globalcors:
corsConfigurations:
'[/**]':
allowedHeaders: "*"
allowedOrigins: "*"
allowedMethods:
- GET
- POST
- DELETE
- PUT
- OPTION
3、访问url:http://localhost:8000/?green=c ,如果你Cookie 有是 x 的,则通过,否则返回错误;
4、局部过滤器配置:
- id: test_query_route
uri: lb://register-server
predicates:
- Query=shadow
filters:
# 下面类 AvGatewayFilterFactory 中 的AV 对应 此配置 AV (AvGatewayFilterFactory中GatewayFilterFactory之前的部分)
- Av=true
核心代码 必须继承 AbstractGatewayFilterFactory<AvGatewayFilterFactory.Config> 类:
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import java.util.Arrays;
import java.util.List;
@Component
public class AvGatewayFilterFactory extends AbstractGatewayFilterFactory<AvGatewayFilterFactory.Config> {
public AvGatewayFilterFactory(){
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
if(!config.enable){
return chain.filter(exchange);
}
/**
* validate 验证
*/
ServerHttpRequest request = exchange.getRequest();
MultiValueMap<String, HttpCookie> cookies = request.getCookies();
for (String s : cookies.keySet()) {
if(s.equals("e")){
System.out.println("--------AbstractGatewayFilterFactory--------------");
return chain.filter(exchange);
}
}
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
};
}
@Override
public List<String> shortcutFieldOrder() {
//对应Config 类当中的变量
return Arrays.asList("enable");
}
public static class Config{
private boolean enable;
public boolean isEnable() {
return enable;
}
public void setEnable(boolean enable) {
System.out.println(enable);
this.enable = enable;
}
}
}
然后访问思路和全局配置一样,结果ok;
二,原生限流 redis 集成
官方文档在这里:
1、引入jar
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
2、核心配置如下:
server:
port: 8000
spring:
application:
name: register-gateway-8000
redis:
database: 3
host: 10.130.16.26
password: redispwd
port: 289
jedis:
pool:
max-active: 500
max-wait: -1
max-idle: 8
min-idle: 0
timeout: 0
cloud:
gateway:
routes:
- id: requestratelimiter_route
uri: https://www.baidu.com
order: 10000
predicates:
# - Query=green
# - Path=/uas/{segment}
- Before=2021-05-07T19:52:47.789+08:00
# - Path=/admin/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 1 # 令牌桶的容积
redis-rate-limiter.burstCapacity: 1 # 流速 每秒
key-resolver: "#{@userKeyResolver}" #SPEL表达式去的对应的bean
- StripPrefix=1 #表示二级url路径转发
3、核心代码:
@EnableDiscoveryClient
@SpringBootApplication
@RestController
public class Application_8000 {
public static void main(String[] args) {
SpringApplication.run(Application_8000.class,args);
}
@Bean
public KeyResolver userKeyResolver(){
return new KeyResolver() {
@Override
public Mono<String> resolve(ServerWebExchange exchange) {
HttpCookie httpCookie=null;
ServerHttpRequest request = exchange.getRequest();
MultiValueMap<String, HttpCookie> cookies = request.getCookies();
for (Map.Entry<String, List<HttpCookie>> stringListEntry : cookies.entrySet()) {
if(stringListEntry.getKey().equals("c")){
httpCookie = stringListEntry.getValue().get(0);
}
}
return Mono.just(httpCookie.getValue());
}
};
}
}
4、存session的代码:
@RestController
public class LoginController {
//先登录此接口 存session ,
@GetMapping("/validate")
public void validate(ServerHttpResponse response){
System.out.println("OK!!!!!");
response.addCookie(ResponseCookie.from("c","nandao").build()
);
}
}
5、启动后先访问:http://localhost:8000/validate 成功后首次访问 http://localhost:8000 进入百度页面:
6、如果点击刷新非常快(一秒内多次访问),则会进入错误页面:
7、到此说明限流成功。
8、也可以多维度限流设置:
/**
* 自定义限流标志的key,多个维度可以从这里入手
* exchange对象中获取服务ID、请求信息,用户信息等
*/
@Bean
KeyResolver remoteAddrKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}
到此gateway 路由功能分析完毕,以后有机会我们共同学习其源码,敬请期待!