提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
上篇文章介绍完Feign远程调用的学习,今天来介绍Gateway网关
提示:以下是本篇文章正文内容,下面案例可供参考
一、Gateway是什么?
官方说法:Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等响应式编程和事件流技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。
简单来理解就是网管,去上网,允不允许,上哪台等等都要经过它的管理
有些功能只对内开放,目的是防止某些微服务的接口向外暴露。
网关的核心功能特性:
-
请求路由:根据某些规则,将请求转发某个微服务中,当微服务数量多时,需要负载均衡
-
权限控制:检验用户是否拥有访问资格
-
限流:当请求数量多的时候,按照下流微服务能够接收的量去放行请求
二、搭建Gateway网关
1.创建Gateway-service模块
2.导入依赖包
Gateway这个微服务需要被nacos注册
<dependencies>
<!--nacos服务发现依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--网关依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
3.编写启动类
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class,args);
}
}
三、关于Gateway的配置编写
1:在application.yml中编写Gateway的配置
server:
port: 10010 # 网关接口
spring:
application:
name: gateway # 服务名称
cloud:
nacos:
server-addr: localhost:8848 # nacos地址
gateway:
routes: # 路由
- id: user-service # 路由id,自定义,唯一
# uri: http://127.0.0.1:8081 http地址写死不方便改变
uri: lb://userservice # 路由的目标地址 lb是负载均衡,后面跟服务名称
predicates: # 路由断言,判断访问地址是否符合规则
- Path=/user/** # 路径匹配,是否是/user/,是则录入路由目标地址
- id: order-service
uri: lb://orderservice
predicates:
- Path=/order/**
来解析一下里面的属性
1:routes:路由
2:id:路由的名字
3:uri:路由的目标地址,当断言提高时会将目标地址替换localhost:10010从而转发到微服务
4:predicates:路由断言,判断是否转发的规则
我们来重点解析predicates
2:predicates的学习
spring为我们提供了11种基本工厂,不需要完全记住,当需要的时候就查询即可
断言的作用可以理解为路由是否向你开启的规则
四、Gateway的内部结构
上面的讲解介绍的是Gateway的入口,就像大门一样,即使你成功进入,内部仍然有许多拦截。
1:Gateway的结构图
从上图不难看出,进入门口(路由)后,后面还有过滤器的存在
过滤器的作用就是对微服务的请求和相应做出处理
2:什么是过滤器
1:过滤器的作用
过滤器的作用就是对微服务的请求和相应做出处理
那么它是如何处理的呢,先来看一下它的规则
2:过滤器的规则
下面是过滤器工厂GatewayFilterFactory
以上列出几个常用的规则,无需死记硬背,要使用的时候可以上spring官网查阅
过滤器有三种
1:路由过滤器
2:默认过滤器
3:全局过滤器
首先是默认过滤器
3:路由过滤器
路由过滤器顾名思义是只针对某个路由的,下面是它的配置方式
- id: order-service
uri: lb://orderservice
predicates:
- Path=/order/**
filters: # 此路由器的过滤器
- AddRequestHeader=admin,niubi! # 添加请求头,逗号前是变量名,逗号后是值
为order-service添加过滤器,我们来演示一下
当我们访问网关的时候(访问内容下面会细讲,现在可以理解为访问order-service)它的路由过滤器会自动为请求添加一个请求头,变量名为admin,值为niubi!
在web层通过@RequestHeader注解来获取请求头就可以查看是否成功
@GetMapping("{orderId}")
public Order queryOrderByUserId(@PathVariable("orderId") Long orderId, @RequestHeader("admin") String admin) {
System.out.println(admin);
// 根据id查询订单并返回
return orderService.queryOrderById(orderId);
}
4:默认过滤器
默认过滤器的作用范围是全部的路由,顾名思义就是所有路由都有它的存在。
上文说到路由(门口)不只有一个
下面是默认过滤器的配置
server:
port: 10010 # 网关接口
spring:
application:
name: gateway # 服务名称
cloud:
nacos:
server-addr: localhost:8848 # nacos地址
gateway:
routes:
- id: user-service # 路由id,自定义,唯一
# uri: http://127.0.0.1:8081 地址写死不方便改变
uri: lb://userservice # 路由的目标地址 lb是负载均衡,后面跟服务名称
predicates: # 路由断言,判断访问地址是否符合规则
- Path=/user/** # 路径匹配,是否是/user/,是则录入路由目标地址
- id: order-service
uri: lb://orderservice
predicates:
- Path=/order/**
filters: # 此路由器的过滤器
- AddRequestHeader=admin,niubi! # 添加请求头
default-filters: #默认过滤器,范围全局-----------------------------------
由于默认过滤器的作用范围是所有路由,所以它的等级比普通的路由过滤器不同,是跟routes一级
这里要十分注意缩进位置
它的配置方式和路由过滤器是一模一样的规则。
spring:
application:
name: gateway # 服务名称
cloud:
nacos:
server-addr: localhost:8848 # nacos地址
gateway:
routes:
- id: user-service # 路由id,自定义,唯一
# uri: http://127.0.0.1:8081 地址写死不方便改变
uri: lb://userservice # 路由的目标地址 lb是负载均衡,后面跟服务名称
predicates: # 路由断言,判断访问地址是否符合规则
- Path=/user/** # 路径匹配,是否是/user/,是则录入路由目标地址
- id: order-service
uri: lb://orderservice
predicates:
- Path=/order/**
# filters: # 此路由器的过滤器
default-filters:
- AddRequestHeader=admin,niubi! # 添加请求头 #默认过滤器,范围全局
5:全局过滤器
全局过滤器GloalFilters和上面几种不同之处在于你需要完成它的逻辑处理
步骤
新建立一个类实现GlobalFilter接口实现它的方法
//设置过滤器优先度 越小优先越强 -2147483647-2147473647
@Order(-1)
//交给spring管理
@Component
public class AuthorizeFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//exchange存放着请求信息,chain负责放行到其他过滤器
//1:获取请求参数
ServerHttpRequest request = exchange.getRequest();
MultiValueMap<String, String> queryParams = request.getQueryParams();
//2:获取参数中的 authorization 参数
String authorization = queryParams.getFirst("authorization");
//3:判断参数
if ("admin".equals(authorization)){
//4:放行
return chain.filter(exchange);
}
//4:拦截
//4.1:设置状态码,作用是告诉用户目前状态而不是单纯的被拦截
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.valueOf(401)); //401模拟未登录的状态
//4.2:拦截
return response.setComplete();
//-------------该拦截器作用是判断用户是否登录(是否携带规定的参数)
}
}
具体效果
当没有携带规定参数会提示401状态
当携带了规定参数则会成功访问
五、过滤器的执行顺序
当编写多个过滤器的时候,Gateway会将他们合并到一个过滤器链(集合)中
它的默认顺序为:默认过滤器--路由过滤器--全局过滤器
但是每一个过滤器都会有一个固定的优先度值order
路由过滤器和默认过滤器的order值由spring 管理,默认为1,存在多个路由过滤器或者默认过滤器时开始递增
而全局过滤器则是可以自定义order值,使用注解定义order,方法如下
当过滤器order值相同时候,它的默认顺序为:默认过滤器--路由过滤器--全局过滤器
六、同一网关Gateway跨域问题
在网关微服务中的配置文件添加
globalcors: # 全局的跨域处理
add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题 cors解决方案是浏览器向服务端发送请求是否准许跨域,这个请求是options,所以要放行
corsConfigurations:
'[/**]': # 拦截所有路径
allowedOrigins: # 允许哪些网站的跨域请求
- "http://localhost:8090"
- "http://www.leyou.com"
allowedMethods: # 允许的跨域ajax的请求方式
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
allowedHeaders: "*" # 允许在请求中携带的头信息
allowCredentials: true # 是否允许携带cookie
maxAge: 360000 # 这次跨域检测的有效期
具体用法以后会说到
七、关于Gateway在springcloud的工作流程图
总结
以上是关于Gateway的学习