SpringCloud-Gateway的使用
SpringCloud-gateway 的使用
初步使用
引入依赖
gateway 是一个独立的 web 服务器,他使用的是 netty 的服务器,所以我们的项目不能包含 spring-boot-starter 依赖。为了避免被继承依赖,所以我们新建一个项目,自建依赖。
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<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>配置属性
这里使用了 predicates 里面的 Path Router
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15spring:
application:
name: spring-cloud-gateway
cloud:
gateway:
routes:
- predicates:
- Path=/gateway/**
filters:
- StripPrefix=1
uri: http://localhost:8166/
server:
port: 8184需要注意的是 ,没有提示,大小写一定要区分(Path,StripPrefix),Path 和等号之间不能有空格 !!!。
测试
上面配置的意思是,对于请求地址是以/gateway 开头的地址,全部转发到 http://localhost:8166/这个地址上面去。
1
2## 访问 http://localhost:8184/gateway/orderId
qaq
Predicate
Predicate 断言,可以配置多个,且的关系。通过判断条件来决定请求是否被路由到。
Cookie Route Predicate Factory 的使用
增加配置
1 | spring: |
多个 router 可以通过 id 区分,每个 router 之间不会相互干扰。
新增的 cookie_router 的意思是,如果请求中带有 cookie,key 是 name,value 是 zsf 的,将会被转发到http://www.baidu.com的请求上。
1 | curl --location --request POST 'http://localhost:8184' \ |
自定义 Predicate
Route Predicate Factories
SpringCloud 的官网上面默认提供了 11 种 predicate,如果我们需要自定义 Predicate,主要继承 AbstractRoutePredicateFactory 类就可以了
需要注意的是 predicate 的命令是有规律的,前缀为 predicate 的名字,后面必须跟上 RoutePredicateFactory
创建 AbstractRoutePredicateFactory 新的子类 AuthRoutePredicateFactory
1
2
3
4
5
6
7
8
9
public class AuthRoutePredicateFactory extends AbstractRoutePredicateFactory<Config> {
public AuthRoutePredicateFactory() {
super(Config.class);
}
private static final String NAME_KEY = "name";
private static final String NAME_VALUE = "value";@Override
public ListshortcutFieldOrder() {
return Arrays.asList(NAME_KEY, NAME_VALUE);
}@Override
public Predicateapply(Config config) {
return (exchange -> {
HttpHeaders headers = exchange.getRequest().getHeaders();
Listlist = headers.get(config.getName());
return !list.isEmpty();
});
}public static class Config {
private String name; private String value; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getValue() { return value; } public void setValue(String value) { this.value = value; }
}
}1
2
3
需要加上 spring 的 bean 注解 component,才能被加载到添加配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14spring:
application:
name: spring-cloud-gateway
cloud:
gateway:
routes:
- id: auth_route
predicates:
- Path=/auth/**
- Auth=Authorization
uri: http://www.google.com
server:
port: 8184上述配置意思是,对于请求路径以 auth 开头,包含以 Authorization 为 key 的请求头的请求,将会被转发到http://www.google.com
使用
1
2curl --location --request POST 'http://localhost:8184/auth' \
--header 'Authorization: xxxx'
Filter
filter 过滤器,可以配置多个,且的关系。
SpringCloud 默认提供了 31 种 filter 的实现来我们选择。
StripPrefix 主要用来做路径转发,Retry 用来做重试,RequestRateLimiter 用来做限流
自定义过滤器
继承 AbstractGatewayFilterFactory
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
public class DiyGatewayFilterFactory extends AbstractGatewayFilterFactory<Config> {
private static final String NAME_KEY = "name";
private static final String NAME_VALUE = "value";
public DiyGatewayFilterFactory() {
super(Config.class);
}
public List<String> shortcutFieldOrder() {
return Arrays.asList(NAME_KEY, NAME_VALUE);
}
public GatewayFilter apply(Config config) {
return ((exchange, chain) -> {
System.out.println("[pre] Filter Requests,name:" + config.getName());
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
System.out.println("[post] Filter Requests");
}));
});
}
public static class Config {
private String name;
private String value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16spring:
application:
name: spring-cloud-gateway
cloud:
gateway:
routes:
- id: filter_router
predicates:
- Path=/filter/**
filters:
- StripPrefix=1
- Diy=Hello Filter
uri: http://localhost:8166/
port: 8184这个过滤器没有实际作用,主要是对于请求地址以 filter 开头的请求打印日志
调用
1
curl --location --request GET 'http://localhost:8184/filter/orderId'
结果
1
2[pre] Filter Requests,name:Hello Filter
[post] Filter Requests
RequestRateLimiter 的使用
实现 KeyResolver
1
2
3
4
5
6
7
8
9
10
public class IpAddressKeyResolve implements KeyResolver {
public Mono<String> resolve(ServerWebExchange exchange) {
String hostAddress = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
System.out.println(hostAddress);
return Mono.just(hostAddress);
}
}引入依赖
1
2
3
4<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25spring:
application:
name: spring-cloud-gateway
cloud:
gateway:
routes:
- id: ratelimiter_route
predicates:
- Path=/ratelimiter/**
filters:
- StripPrefix=1
- name: RequestRateLimiter
args:
deny-empty-key: true
keyResolver: '#{@ipAddressKeyResolve}'
redis-rate-limiter.replenishRate: 1
redis-rate-limiter.burstCapacity: 1
uri: http://localhost:8166/
redis:
host: localhost
port: 6379
server:
port: 8184需要配置 redis。
keyResolver: ‘#{@ipAddressKeyResolve}’ 指定对应的限流的判定值,案例中是 ip 地址
redis-rate-limiter.replenishRate: 1,每秒最多请求 1 次
redis-rate-limiter.burstCapacity: 1 ,最多缓存 1 个请求数
访问
1
http://localhost:8184/ratelimiter/orderId
超出频率后返回
1
2该网页无法正常运作如果问题仍然存在,请与网站所有者联系。
HTTP ERROR 429注意点
这里面如果 redis 端口配置错误,报错:
1
io.lettuce.core.RedisException: Invalid first byte: 74
如果 redis 没有启动,不会有任何报错信息,这 2 种情况需要自己注意。