什么是网关

网关统一服务入口,可方便实现对平台众多服务接口进行管控

image-20210812102043597

网关的作用

  • 网关统一所有微服务入口
  • 网关可以实现请求路由转发(router dispatcher)以及请求过程负载均衡
  • 访问服务的身份认证、防报文重放和防数据篡改、功能调用的业务鉴权、相应数据的脱敏、流量与并发控制,甚至基于API调用计量或者计费等。

GateWay

GateWay是Spring团队开发的网关组件。

主要的作用:动态路由,服务统一管理,请求过滤

GateWay = 路由转发(router)+请求过滤(filter)

GateWay网关使用

1、首先在父项目中创建一个SprinBoot项目

注意:因为GateWay使用的WebFlux 一步非阻塞IO模型,所以如果使用SpringMvc会发生冲突,所以不要引入SpringWeb依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!--        引入consul依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!-- 引入健康检查依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 引入gateway依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

2、创建完一个SpringBoot应用之后我们要去配置文件(注意缩进)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
server:
port: 9797
spring:
application:
name: GATEWAY
cloud:
consul:
port: 8500
host: localhost
gateway:
routes:
- id: category_router #路由标识唯一对象 这里不要忘掉- 这里的意思是一个list因为一个项目网关下面管理多个服务的地址
uri: http://localhost:8787
predicates:
- Path=/category #一个服务对应着多个请求,所以这里也是一个list
- id: product_router #路由标识唯一对象
uri: http://localhost:8686
predicates:
- Path=/product

Java代码配置网关

这个就很简单了,就是简单的写一个配置类(Java代码中代码的优先级高于配置文件)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* @author bestrookie
* @date 2021/8/12 4:13 下午
*/
@Configuration
public class GateWayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder){
return builder.routes()
.route("category_routor",r-> r.path("/category").uri("http://localhost:8787"))
.route("proudct_route",predicateSpec -> predicateSpec.path("/product").uri("http://localhost:8686"))
.build();
}
}

GateWay解析规则

有的小伙伴可能对路径的解析比较迷惑,下面简单说一下

Gate是根据配置文件中predicates去匹配地址栏比如

localhost:9797/category

GateWay获取配置文件匹配category

image-20210812173152195

在这个我就用了一个特殊的例子,两个的地址一样咋办?这个GateWay会默认第一个,哎,就是这么随意。在实际开发中要是写出这么不规范的接口路径,个人建议:提桶跑路,我们一般在@RequestMapping("/接口标识符")来区分接口。

网关在路由转发时实现请求负载均衡

上面说了不同服务路径重名可以用服务名来区分,那么在据集群中呢怎么分辨呢,这个可是服务名都是一样的,这样在uri中直接写死为服务的某一个节点,这样是无法实现负载均衡的。

配置负载均衡

1
2
3
4
5
6
7
8
9
10
11
routes:
- id: category_router #路由标识唯一对象
#uri: http://localhost:8787
uri: lb://CATEGORY
predicates:
- Path=/category/**
- id: product_router #路由标识唯一对象
#uri: http://localhost:8686
uri: lb://PRODUCT
predicates:
- Path=/product/**

改写uri中路径的写法:lb://CATEGORYlb是负载均衡的意思,后面跟着的服务在注册中心注册的服务名称

由此可以看出GateWay也是集成了Ribbon组件

网关的断言(predicate)和过滤(filter)

Gateway Handler MappingGateWebHandler组成了断言(predicate)下面的一系列组成了(filter)

网关 GateWay = 断言 + 过滤

断言的使用(Route Predicate Factories)

SpringCloud给我们内置了许多的Predicate

1
2
3
4
5
6
7
8
- Path=/category/**  #路径断言,符合规定的路径才可以访问
- After=2017-01-20T17:42:47.789-07:00[America/Denver] #代表该路由规则必须在指定的之后才能生效
- Before=2017-01-20T17:42:47.789-07:00[America/Denver] #代表该路由必须在指定时间之前有效,过了时间失效
- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver] #代表路由规则在某个时间段有效
- Cookie=chocolate, ch.p #携带只能cookie请求才能访问
- Cookie=chocolate,[A-Za-z0-9] #限定第二个字符符合正则表达式
- Header=X-Request-Id, \d+ #请求必须含有指定请求头才行,第二个字符也是正则表达式
- Method=GET,POST #限定请求方式类型

搭配文档食用更香

filter的使用

同样SpringCloud内置了许多的filter,同样filter的使用是需要在配置中添加filters:

1
2
3
4
5
6
7
8
9
filters:
- AddRequestHeader=key, value #这个是AddRequestHeader Filter 用来给路由对象的所有转发请求加入指定请求头信息
- AddRequestParameter=参数名, 参数值 # AddRequestParamter Filter 用来给路由对象的所有转发请求加入指定请求参数
- AddResponseHeader=key, value # AddResponseHeader Filter 用来给路由对象的所有转发请求的响应加入指定头信息
- PrefixPath=/mypath # PrefixPath Filter 用来给路由对象的所有转发请求的url加入指定前缀信息
#例如:浏览器访问网关地址 /list 前缀路径为/mypath 转发都后端服务地址为: uri + 前缀 + 地址栏路径 ===> uri/mypath/list
-StripPrefix=n # StripPrefix Filter 用来给路由对象的所有转发请求的url去掉指定n个前缀
#例如:浏览器访问网关地址:/product/list StripPefix=1 =====> /list 后端接受的接口就是 /list

这里只是比较常用的过滤器,搭配文档食用更香

自定义全局Filter

当然如果没有什么特殊要求,为了方便我们还可以自动全局filter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* @author bestrookie
* @date 2021/8/16 9:23 上午
*/
@Configuration
public class GlobalGateWayFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//获取httprequest对象
ServerHttpRequest request = exchange.getRequest();
//获取httpresponse对象
ServerHttpResponse response = exchange.getResponse();
System.out.println("经过全局Filter处理");
Mono<Void> filter = chain.filter(exchange); //放行filter继续向后执行
System.out.println("响应回来Filter处理");
return filter;
}
//order是排序,相当于给这个filter一个序号,-1的意思是优先指向,其余默认按照自然数字排序
@Override
public int getOrder() {
return -1;
}
}

通过web查看路由详情规则

http://localhost:7979/actuator/gateway/routes

在配置文件中配置

1
2
3
4
5
management:
endpoints:
web:
exposure:
include: "*"

评论