网关 Spring Cloud Gateway
网关 Spring Cloud Gateway
1 目标
- 网关的作用
- 会配置动态路由
- 会配置过滤器
- 能自定义全局过滤器
2 讲解
(1) Gateway 简介
Spring Cloud Gateway 是Spring Cloud团队的一个全新项目,基于Spring 5.0、SpringBoot2.0、Project Reactor 等技术开发的网关。 ==旨在为微服务架构提供一种简单有效统一的API路由管理方式。==
Spring Cloud Gateway 作为SpringCloud生态系统中的网关,目标是替代Netflix Zuul。Gateway不仅提供统一路由方式,并且==基于Filter链的方式提供网关的基本功能。例如:安全,监控/指标,和限流。==
本身也是一个微服务,需要注册到Eureka
网关的核心功能:过滤、路由
核心概念:通过画图解释
- 路由(route):
- 断言Predicate函数:路由转发规则
- 过滤器(Filter):
(2) 快速入门
实现步骤:
1. 创建gateway-service工程SpringBoot
2. 编写基础配置
3. 编写路由规则,配置静态路由策略
4. 启动网关服务进行测试
实现过程:
(1)创建一个子工程gateway-service
工程坐标:
<artifactId>gateway-service</artifactId>
<groupId>com.itheima</groupId>
<version>1.0-SNAPSHOT</version>
(2)pom.xml依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>springcloud-parent</artifactId> <groupId>com.itheima</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>gateway-service</artifactId> <dependencies> <!--网关依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!-- Eureka客户端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies> </project>
(3)启动类
创建启动类com.itheima.GatewayApplication
,代码如下:
@SpringBootApplication @EnableDiscoveryClient// 开启Eureka客户端发现功能 public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class,args); } }
(4)application.yml配置
# 注释版本 server: port: 18084 spring: application: name: api-gateway # 应用名 # Eureka服务中心配置 eureka: client: service-url: # 注册Eureka Server集群 defaultZone: http://127.0.0.1:7001/eureka
3. 路由配置
通过网关配置一个路由功能,用户访问网关的时候,如果用户请求的路径是以/user
开始,则路由到user-provider
服务去,修改application.yml配置即可实现,配置如下:
spring: application: # 应用名 name: api-gateway cloud: gateway: routes: #id唯一标识,可自定义 - id: user-service-route #路由的服务地址 uri: http://localhost:18081 # 路由拦截的地址配置(断言) predicates: - Path=/user/**
启动GatewayApplication测试
访问http://localhost:18084/user/find/2
会访问user-provider
服务,效果如下:
(1) 动态路由
刚才路由规则中,我们把路径对应服务地址写死了!如果服务提供者集群的话,这样做不合理。应该是**根据服务名称**,去Eureka注册中心查找服务对应的所有实例列表,然后进行动态路由!
修改映射配置:通过服务名称获取:
修改application.yml
因为已经配置了Eureka客户端,可以从Eureka获取服务的地址信息,修改application.yml文件如下:
上图代码如下:
spring: application: # 应用名 name: api-gateway cloud: gateway: routes: #id唯一标识,可自定义 - id: user-service-route #路由的服务地址 #uri: http://localhost:18081 #lb协议表示从Eureka注册中心获取服务请求地址 #user-provider访问的服务名称。 #路由地址如果通过lb协议加服务名称时,会自动使用负载均衡访问对应服务 uri: lb://user-provider # 路由拦截的地址配置(断言) predicates: - Path=/user/**
路由配置中uri所用的协议为lb时,gateway将把user-provider解析为实际的主机和端口,并通过Ribbon进行负载均衡。
(2 )过滤器
过滤器作为Gateway的重要功能。常用于请求鉴权、服务调用时长统计、修改请求或响应header、限流、去除路径等等…
过滤器的分类
默认过滤器:出厂自带,实现好了拿来就用,不需要实现 全局默认过滤器 局部默认过滤器 自定义过滤器:根据需求自己实现,实现后需配置,然后才能用哦。 全局过滤器:作用在所有路由上。 局部过滤器:配置在具体路由下,只作用在当前路由上。
默认过滤器几十个,常见如下:
过滤器名称 | 说明 |
---|---|
AddRequestHeader | 对匹配上的请求加上Header |
AddRequestParameters | 对匹配上的请求路由 |
AddResponseHeader | 对从网关返回的响应添加Header |
StripPrefix | 对匹配上的请求路径去除前缀 |
详细说明官方链接
(3) 默认过滤器配置
默认过滤器有两个:全局默认过滤器和局部默认过滤器。
全局过滤器:对输出响应头设置属性
对输出的响应设置其头部属性名称为X-Response-Default-MyName,值为itheima
修改配置文件
spring: cloud: gateway: # 配置全局默认过滤器 default-filters: # 往响应过滤器中加入信息 - AddResponseHeader=X-Response-Default-MyName,itheima
查看浏览器响应头信息!
局部过滤器:通过局部默认过滤器,修改请求路径。局部过滤器在这里介绍两种:添加路径前缀、去除路径前缀。
第一:添加路径前缀:
在gateway中可以通过配置路由的过滤器PrefixPath 实现映射路径中的前缀
配置请求地址添加路径前缀过滤器
上图配置如下:
spring: application: # 应用名 name: api-gateway cloud: gateway: routes: #id唯一标识,可自定义 - id: user-service-route #路由的服务地址 #uri: http://localhost:18081 #lb协议表示从Eureka注册中心获取服务请求地址 #user-provider访问的服务名称。 #路由地址如果通过lb协议加服务名称时,会自动使用负载均衡访问对应服务 uri: lb://user-provider # 路由拦截的地址配置(断言) predicates: - Path=/** filters: # 请求地址添加路径前缀过滤器 - PrefixPath=/user default-filters: - AddResponseHeader=X-Response-Default-MyName,itheima
路由地址信息:
配置 | 访问地址 | 路由地址 |
---|---|---|
PrefixPath=/user | http://localhost:18084/find/2 | http://localhost:18081/user/find/2 |
第二:去除路径前缀:
在gateway中通过配置路由过滤器StripPrefix,实现映射路径中地址的去除。通过StripPrefix=1来指定路由要去掉的前缀个数。如:路径/api/user/1将会被路由到/user/1。
配置去除路径前缀过滤器
上图配置如下:
spring: application: # 应用名 name: api-gateway cloud: gateway: routes: #id唯一标识,可自定义 - id: user-service-route #路由的服务地址 #uri: http://localhost:18081 #lb协议表示从Eureka注册中心获取服务请求地址 #user-provider访问的服务名称。 #路由地址如果通过lb协议加服务名称时,会自动使用负载均衡访问对应服务 uri: lb://user-provider # 路由拦截的地址配置(断言) predicates: - Path=/** filters: # 请求地址添加路径前缀过滤器 #- PrefixPath=/user # 去除路径前缀过滤器 - StripPrefix=1 default-filters: - AddResponseHeader=X-Response-Default-MyName,itheima
路由地址信息:
配置 | 访问地址 | 路由地址 |
---|---|---|
StripPrefix=1 | http://localhost:18084/api/user/find/2 | http://localhost:18081/user/find/2 |
StripPrefix=2 | http://localhost:18084/api/r/user/find/2 | http://localhost:18081/user/find/2 |
自定义过滤器案例
自定义过滤器也有两个:全局自定义过滤器,和局部自定义过滤器。
自定义全局过滤器的案例,自定义局部过滤器的案例。
自定义全局过滤器的案例:模拟登陆校验。
基本逻辑:如果请求中有Token参数,则认为请求有效放行,如果没有则拦截提示授权无效
全局过滤器自定义:
实现步骤:
1.在gateway-service工程编写全局过滤器类GlobalFilter,Ordered 2.编写业务逻辑代码 3.访问接口测试,加token和不加token。
实现过程:
在gateway-service
中创建com.itheima.filter.LoginGlobalFilter
全局过滤器类,代码如下:
@Component
public class LoginGlobalFilter implements GlobalFilter, Ordered {
/***
* 过滤拦截
* @param exchange
* @param chain
* @return
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//获取请求参数
String token = exchange.getRequest().getQueryParams().getFirst("token");
//如果token为空,则表示没有登录
if(StringUtils.isEmpty(token)){
//没登录,状态设置403
exchange.getResponse().setStatusCode(HttpStatus.PAYLOAD_TOO_LARGE);
//结束请求
return exchange.getResponse().setComplete();
}
//放行
return chain.filter(exchange);
}
/***
* 定义过滤器执行顺序
* 返回值越小,越靠前执行
* @return
*/
@Override
public int getOrder() {
return 0;
}
}
测试:不携带token <http://localhost:18084/api/user/find/2>
效果如下:
测试:携带token <http://localhost:18084/api/user/find/2?token=abc>
此时可以正常访问。
局部过滤器定义
自定义局部过滤器,该过滤器在控制台输出配置文件中指定名称的请求参数及参数的值
实现步骤:
1. 在gateway-service中编写MyParamGatewayFilterFactory类 2. 实现业务代码:循环请求参数中是否包含name,如果包含则输出参数值 3. 修改配置文件 4. 访问请求测试,带name参数
实现过程:
在gateway_service中编写MyParamGatewayFilterFactory类
@Component
public class MyParamGatewayFilterFactory extends AbstractGatewayFilterFactory<MyParamGatewayFilterFactory.Config> {
/**
* 定义需要处理的参数
*/
public static final String PARAM_NAME = "name";
/****
* 处理过程
* @param config
* @return
*/
@Override
public GatewayFilter apply(MyParamGatewayFilterFactory.Config config) {
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String name = exchange.getRequest().getQueryParams().getFirst("name");
if(!StringUtils.isEmpty(name)){
System.out.println("名字参数:"+name);
}
return chain.filter(exchange);
}
};
}
/***
* 构造函数
*/
public MyParamGatewayFilterFactory() {
super(MyParamGatewayFilterFactory.Config.class);
}
/***
* 处理字段的排序
* @return
*/
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList(PARAM_NAME);
}
/****
* 需要处理的参数
* name:和处理的参数名字保持一致
*/
public static class Config {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
修改application.yml配置文件
测试访问,检查后台是否输出name和itcast;访问<http://localhost:18084/api/user/find/2?name=itheima&tomen=aaa>
会输出。
6 微服务架构加入Gateway后
![SpringCloud微服务架构–加入Gateway后 (1)](images\SpringCloud微服务架构–加入Gateway后 (1).jpg)
- 不管是来自客户端的请求,还是服务内部调用。一切对服务的请求都可经过网关。
- 网关实现鉴权、动态路由等等操作。
- Gateway就是我们服务的统一入口
3. 小结
- 网关的作用
properties 1.为微服务架构提供一种简单有效统一的API路由管理方式 2.可以在网关中实现微服务鉴权、安全控制、请求监控、限流
- 会配置动态路由
properties 使用lb配置,能根据服务名字动态请求。
- 会配置过滤器
properties 默认过滤器:default-filters:
- 能自定义全局过滤器
properties 编写过滤器类,实现GlobalFilter和Ordered,在filter方法中实现过滤。
推荐阅读
-
聊聊Spring Cloud Cli 初体验
-
Spring Cloud Alibaba | Sentinel: 服务限流高级篇
-
Spring Cloud系列-Zuul网关集成JWT身份验证
-
Spring Cloud第七篇 | 声明式服务调用Feign
-
spring cloud 初步搭建1-1(eureka配置)
-
spring cloud Eureka 配置信息
-
SpringCloud之Spring Cloud Stream:消息驱动
-
Spring Cloud Config 配置中心实践过程中,你需要了解这些细节!
-
详解Spring Cloud Eureka多网卡配置总结
-
详解基于Spring Cloud几行配置完成单点登录开发