Gateway网关组件

作用:解耦(解除客户端与微服务的耦合),方便微服务访问地址的维护,服务路由、负载均衡;身份认证和权限校验;请求限流;

网关也会被当成一个微服务注册在nacos上,网关会作为一个与客户端与各种服务的中间人,为客户端提供中转服务。在中转服务时可以做一些与本身业务功能无关的逻辑,比如认证、鉴权、监控、路由转发等等。

相同作用的一些技术对比:

​ ●Nginx+lua脚本:使用nginx的反向代理和负载均衡可以实现对api服务器的负载均衡和高可用;lua脚本语言可以编写一些简单逻辑,具有原子性,完成某些操作。

​ ●Kong : 基于Nginx+Lua开发,性能高,稳定,有多个可用的插件(限流、鉴权等等)可以开箱即用。
问题:只支持Http协议;二次开发,自由扩展困难;提供管理API,缺乏更易用的管控、配置方式。

​ ●Zuul : Netflix开源的网关,功能丰富,使用JAVA开发,易于二次开发
问题:缺乏管控,无法动态配置;依赖组件较多;处理Http请求依赖的是Web容器,性能不如NginxSpring Cloud Gateway

​ ●Gateway : Spring公司为了替换Zuul而开发的网关服务;设计优雅,容易扩展—–spring就是牛逼哈~

Getway配置详解:

​ 1、引入依赖

1
2
3
4
5
6
7
8
9
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

2、编写网关启动类

1
2
3
4
5
6
7
@SpringBootApplication
public class GatewayApplication {

public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}

3、编写路由配置及nacos地址的yml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
spring:
cloud:
nacos:
server-addr: localhost:80
gateway:
routes:
-
id: user-service # 路由id 必填 不重复即可
uri: lb://userService # 路由目标地址
predicates: # 路由断言,判断请求是否符合规则
- 'Path=/user/**' # 判断路径是否以/user开头,如果是则符合
-
id: order-service
uri: lb://orderService
predicates:
- 'Path=/order/**'
application:
name: gateway

server:
port: 10010

路由断言工厂

配置的路由断言是由断言工厂解析的,我们配置的是字符串,路由工厂则取解析

eg

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

spring:
cloud:
nacos:
server-addr: localhost:80
gateway:
routes:
-
id: user-service # 路由id 必填 不重复即可
uri: lb://userService # 路由目标地址
predicates: # 路由断言,判断请求是否符合规则
- 'Path=/user/**' # 判断路径是否以/user开头,如果是则符合
-
id: order-service
uri: lb://orderService
predicates:
- 'Path=/order/**'
- After=2023-01-14T23:38:47.789+08:00[Asia/Shanghai]
application:
name: gateway

server:
port: 10010

过滤器工厂

作用:可以对进入网关的请求和服务的响应作处理。

spring大哥到目前位置提供了37中不同的路由器过滤器工厂,不明白可以去读文档

编写配置文件

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

spring:
cloud:
nacos:
server-addr: localhost:80
gateway:
routes:
-
id: user-service # 路由id 必填 不重复即可
uri: lb://userService # 路由目标地址
predicates: # 路由断言,判断请求是否符合规则
- 'Path=/user/**' # 判断路径是否以/user开头,如果是则符合
filters:
- AddRequestHeader=IHeader,this is filter
-
id: order-service
uri: lb://orderService
predicates:
- 'Path=/order/**'
- After=2023-01-14T23:40:00+08:00[Asia/Shanghai]
application:
name: gateway

server:
port: 10010

修改代码,演示展现

1
2
3
4
5
6
7
8
@GetMapping("/{id}")
public User queryById(@PathVariable("id") Long id,
@RequestHeader(value = "IHeader", required = false) String IHeader) {
System.out.println(IHeader);
return userService.queryById(id);

}

访问user-service的接口即可看到打印 this is filter

这里展示的是默认过滤器,默认过滤器对所有请求都生效

●全局配置

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
spring:
cloud:
nacos:
server-addr: localhost:80
gateway:
routes:
-
id: user-service # 路由id 必填 不重复即可
uri: lb://userService # 路由目标地址
predicates: # 路由断言,判断请求是否符合规则
- 'Path=/user/**' # 判断路径是否以/user开头,如果是则符合
-
id: order-service
uri: lb://orderService
predicates:
- 'Path=/order/**'
- After=2023-01-14T23:40:00+08:00[Asia/Shanghai]
default-filters:
- AddRequestHeader=IHeader,this is filter
application:
name: gateway

server:
port: 10010

访问user-service的接口即可看到打印 this is filter

全局过滤

实现:实现GlobalFilter接口即可

区别:和全局配置过滤器作用相同,GatewayFilter通过配置定义,处理逻辑是固定的。而GlobalFiter的逻辑需要自己写代码实现。

1
2
3
4
5
6
public class IFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return null;
}
}

eg

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 过滤器链上的优先级 越低优先级越高
@Order(-1)
@Component
public class IFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 1.获取请求参数
ServerHttpRequest request = exchange.getRequest();
MultiValueMap<String, String> queryParams = request.getQueryParams();
// 2.获取某个参数
String auth = queryParams.getFirst("username");
// 3.业务
if ("admin".equals(auth)) {
// 放行
return chain.filter(exchange);
}
// 修改返回状态码
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
// 拦截
return exchange.getResponse().setComplete();
}
}

注解@Order(-1)指明过滤器的执行顺序

​ @Component导入ioc容器

过滤器执行顺序
不管是yml中配置的filters、default-filters还是GlobalFilter,其本质都是GatewayFilter。所以他们的执行顺序是由他们的order值决定,他们的order值有以下规则:路由过滤器和默认过滤器的order由spring指定,默认是按照声明顺序从1递增。GlobalFilter的Order值由我们决定
当过滤器的order值相同时,会按照defaultFilter > 路由过滤器 > GlobalFliter的顺序执行