【微服务】6、一篇文章学会使用 SpringCloud 的网关

news/2024/12/29 8:29:47/

目录

  • 一、网关作用
  • 二、网关的技术实现
  • 三、简单使用
  • 四、predicates
    • (1) 网关路由可配置的内容
    • (2) 路由断言工厂(Route Predicate Factory)
  • 五、filters
    • (1) GatewayFilter
    • (2) 给全部进入 userservice 的请求添加请求头
    • (3) 全局过滤器 —— GlobalFilter
    • (4) 过滤器的执行顺序
  • 六、网关跨域
    • (1) 跨域
    • (2) 网关跨域处理

一、网关作用

📗 身份认证、权限校验
📗 服务路由、负载均衡
📗 请求限流

在这里插入图片描述

二、网关的技术实现

📝 在 SpringCloud 中有两种网关的技术实现
✏️ gateway(比 zuul 新)
✏️ zuul

✒️ Zuul 是基于 Servlet 实现的,属于阻塞式编程
✒️ Gateway 是基于 Spring5 中提供的 WebFlux 实现的。属于响应式编程,具有更好的性能

三、简单使用

✏️ 网关是一个新的微服务
✏️ 需要通过 nacos 进行服务注册和发现

🎄 (1) 创建新的模块(module),引入 SpringCloudGateway 和 Nacos 服务发现依赖

  <dependencies><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></dependencies>

🎄 (2)把网关服务注册到 nacos 中,并编写路由配置

server:port: 10010 # 网关服务的端口号
spring:application:name: gateway # 服务名cloud:nacos:server-addr: localhost:8848 # nacos 服务发现地址gateway: # 网关相关配置routes: # 网关的路由配置- id: userservice # 路由编号(自定义), 保持唯一uri: lb://userservice # 路由的目标地址【lb: load balance】# uri: http://127.0.01:8081 # 路由的目标地址(直接写死)predicates: # 判断(断言)怎样的请求会被路由- Path=/users/** # 若请求路径是【/users/】开头的就路由到此- id: orderserviceuri: lb://orderservicepredicates:- Path=/orders/**

在这里插入图片描述

四、predicates

(1) 网关路由可配置的内容

✒️ id: 路由的唯一标识
✒️ uri:路由目的地【① lb: load balance;② http(不推荐)】
✒️ predicates:路由断言(判断请求是否符合要求,符合则路由转发到对应的 uri 的服务器)
✒️ filters:路由过滤器(处理请求响应

(2) 路由断言工厂(Route Predicate Factory)

📝 在配置文件中写的断言规则只是字符串(它会被 Predicate Factory 读取和处理,并转变为路由判断的条件)


✏️ Path=/user/** 是按照路径进行匹配
✏️ 是通过 PathRoutePredicateFactory 类来处理的

在这里插入图片描述


✏️ SpringCloudGateway 中的断言工厂:
在这里插入图片描述

五、filters

(1) GatewayFilter

📝 GatewayFilter 是网关中提供的一种过滤器(可对进入网关的请求和微服务的响应做处理)

在这里插入图片描述

官方提供了三十多种过滤器工厂:
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories

在这里插入图片描述

(2) 给全部进入 userservice 的请求添加请求头

spring:application:name: gateway # 服务名cloud:gateway: # 网关相关配置routes: # 网关的路由配置- id: userservice # 路由编号(自定义), 保持唯一uri: lb://userservice # 路由的目标地址【lb: load balance】# uri: http://127.0.01:8081 # 路由的目标地址(直接写死)predicates: # 判断(断言)怎样的请求会被路由- Path=/users/** # 若请求路径是【/users/】开头的就路由到此filters: # 过滤器- AddRequestHeader=color, skyblue- id: orderserviceuri: lb://orderservicepredicates:- Path=/orders/**
 @GetMapping("getUserById/{id}")public User getUserById(@PathVariable Long id,@RequestHeader(value = "color", required = false) String color) {log.info("请求头: {}", color);return userService.getUserById(id);}

默认过滤器 default-filters 会对全部的路由请求都生效

spring:application:name: gateway # 服务名cloud:nacos:server-addr: localhost:8848 # nacos 服务发现地址gateway: # 网关相关配置routes: # 网关的路由配置- id: userservice # 路由编号(自定义), 保持唯一uri: lb://userservice # 路由的目标地址【lb: load balance】# uri: http://127.0.01:8081 # 路由的目标地址(直接写死)predicates: # 判断(断言)怎样的请求会被路由- Path=/users/** # 若请求路径是【/users/】开头的就路由到此
#          filters: # 过滤器
#            - AddRequestHeader=color, skyblue- id: orderserviceuri: lb://orderservicepredicates:- Path=/orders/**default-filters: # 默认过滤器- AddRequestHeader=color, green

(3) 全局过滤器 —— GlobalFilter

📝 全局过滤器的作用: 处理一切进入网关的请求微服务响应,与GatewayFilter 的作用一样
📝 区别:GatewayFilter 通过配置定义,处理逻辑是固定的
📝 GlobalFilter 的逻辑需要自己写代码实现


📚 需求:定义全局过滤器,拦截并判断用户身份

定义全局过滤器,拦截请求。判断请求参数是否满足以下条件:
① 参数中是否有 authorization
② authorization 的参数值是否是 admin
若 ① 和 ② 同时满足,则放行;否则拦截

// @Order(value = 6) // 过滤器执行顺序(值越小,优先级越高)
@Component // 放入 IoC
public class GlobalGatewayFilter implements GlobalFilter , Ordered {/*** 拦截并处理全部的请求,处理成功后通过 chain 进入下一个过滤器** @param exchange 请求上下文(可获取 Request、Response 等信息)* @param chain    放行该请求,进入下一过滤器* @return 返回,标识当前过滤器结束*/@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 获取请求参数// 该请求是 WebFlux 中的(与 HttpServletRequest 不同)ServerHttpRequest request = exchange.getRequest();// 获取请求参数(键值对)MultiValueMap<String, String> paramMap = request.getQueryParams();String paramVal = paramMap.getFirst("authorization");if (paramVal == null || !paramVal.equals("admin")) {// 拦截(返回)ServerHttpResponse response = exchange.getResponse();// 未登录状态码response.setStatusCode(HttpStatus.UNAUTHORIZED);return response.setComplete(); // 返回}// 放行return chain.filter(exchange);}@Overridepublic int getOrder() {return 6;}
}

在这里插入图片描述

(4) 过滤器的执行顺序

📚 请求进入网关会碰到三类过滤器:当前路由的过滤器、DefaultFilter、GlobalFilter

📚 请求路由后,会将当前路由过滤器、DefaultFilter、GlobalFilter 合并为一个过滤器链(集合)中,然后进行排序。排序之后,依次执行每个过滤器。

在这里插入图片描述


📚 每个过滤器都必须指定一个 int 类型的 order 值【order 值越小,优先级越高,执行顺序越靠前】
📚 GlobalFilter 通过实现 Ordered 接口或添加 @Order 注解来指定 order 值
📚 路由过滤器和 DefaultFilter 的 order 值由 Spring 指定【在各自过滤器内部按照声明顺序 从1 递增】
📚 当过滤器的 order 值一样时,优先级是:DefaultFilter > 路由过滤器 > GlobalFilter

server:port: 10010
spring:application:name: gatewaycloud:nacos:server-addr: localhost:8848gateway:routes:- id: userserviceuri: lb://userservicepredicates:- Path=/users/**filters: # 路由过滤器- AddRequestHeader=color, red # order = 1- AddRequestHeader=color, blue # order = 2- AddRequestHeader=color, green # order = 3default-filters: # 默认过滤器- AddRequestHeader=name, zgq # order = 1- AddRequestHeader=name, ytr # order = 2- AddRequestHeader=name, zhn # order = 3

  • org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters(): ① 加载 DefaultFilter;② 加载路由过滤器;③ 合并 DefaultFilter 和路由过滤器
  • org.springframework.cloud.gateway.handler.FilteringWebHandler#handle(): ① 加载全局过滤器;② 与 DefaultFilter 和路由过滤器合并;③ 根据合并后的 order 值排序;④ 组织过滤器链

六、网关跨域

(1) 跨域

浏览器有个同源策略(Same-Origin Policy):默认情况下,AJAX 请求只能发送给同源的 URL

📚 AJAX:Asynchronous Javascript And XML【异步 JavaScript 和 XML】

  • 同源指 ① 协议、② 域名(IP)、③ 端口 相同
  • img、script、link、iframe、video、audio 等标签不受同源策略约束

在这里插入图片描述


跨域问题: 浏览器要求发送请求的来源和接收请求的接口的协议、域名和端口必须相同,否则该请求会被浏览器拦截


📚 CORS(Cross-Origin Resource Sharing):跨域资源共享

(2) 网关跨域处理

在这里插入图片描述

  • 要访问 http://localhost:10010/orders/getOrderById/101?authorization=admin 地址的资源
  • 发送请求的来源是 http://localhost:8082/#/pages/index/index

❌ 端口不相同(不符合浏览器的同源策略)

📚 跨域访问检查发送的是 OPTIONS 请求
📚 跨域访问检查有效期要合理

spring:cloud:gateway: # 网关相关配置globalcors: # 全局跨域处理add-to-simple-url-handler-mapping: true # 防止 options 请求被拦截cors-configurations:'[/**]': # 拦截全部路径allowedOrigins: # 允许跨域访问的来源- "http://localhost:8082"allowedMethods: # 允许跨域访问的请求方式- "GET"- "POST"- "DELETE"- "PUT"- "OPTIONS"allowedHeaders: "*" # 允许跨域访问携带请求头信息allowCredentials: true # 允许跨域访问携带 cookiemaxAge: 360000 # 本次跨域访问检查的有效期

http://www.ppmy.cn/news/48600.html

相关文章

RK3568平台开发系列讲解(设备驱动篇)V4L2程序实现流程

🚀返回专栏总目录 文章目录 一、V4L2 进行视频采集二、命令标识符三、V4L2程序实例3.1、打开设备3.2、查询设备属性3.3、显示所有支持的格式3.4、设置图像帧格式3.5、申请缓冲区3.6、将申请的缓冲帧从内核空间映射到用户空间3.7、将申请的缓冲帧放入队列,并启动数据流3.8、启…

pycuda基础实例代码

更多内容请查看 www.laowubiji.com 以下是一个简单的 PyCuda 示例程序。​ import pycuda.driver as drv import pycuda.autoinit import numpy as np#设置GPU设备并获取当前设备信息 drv.init() dev drv.Device(0) print(设备名称: dev.name()) print(设备计算能力: st…

【SCI电气】考虑不同充电需求的电动汽车有序充电调度方法(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

一文详解Python中多进程和进程池的使用方法

这篇文章将介绍Python中多进程和进程池的使用方法&#xff0c;并提供一些实用的案例供大家参考&#xff0c;文中的示例代码讲解详细&#xff0c;感兴趣的小伙伴可以了解一下 目录 Python是一种高级编程语言&#xff0c;它在众多编程语言中&#xff0c;拥有极高的人气和使用率。…

Java线程基础知识

## 补充内容&#xff1a; 1.虚拟机线程管理的接口&#xff0c;获取所有线程id和线程名 //虚拟机线程管理的接口ThreadMXBean threadMXBean ManagementFactory.getThreadMXBean();ThreadInfo[] threadInfos threadMXBean.dumpAllThreads(false, false);for(ThreadInfo threadI…

一条记录的多幅面孔-事务的隔离级别与 MVCC

一、事务隔离级别 引出&#xff1a;**事务的隔离性要求&#xff0c;**理论上在某个事务对某个数据进行访问时&#xff0c;其他事务应该进行排队&#xff0c;当该事务提交之后&#xff0c;其他事务才可以继续访问这个数据。我们既想保持事务的 隔离性 &#xff0c;又想让服务器…

职场危机波及到你了吗?社科院与杜兰大学金融管理硕士项目为你重塑核心竞争力

现在职场&#xff0c;危机四伏&#xff0c;每个人都面临着潜在的危机。职场小白&#xff0c;时时忧心自己的工作是否出错&#xff0c;是否能安全度过试用期&#xff1b;面对新人辈出&#xff0c;职场的前辈也担心被拍在沙滩上。面对竞争激烈的职场&#xff0c;你有感到危机吗&a…

Vue.js过滤器filters

目录 一、局部过滤器 二、全局过滤器 三、过滤器串联 四、过滤器接收多个参数 Vue.js允许自定义过滤器&#xff0c;过滤器的作用可被用于一些常见的文本格式化&#xff08;也就是修饰文本&#xff0c;但是文本内容不会改变&#xff09; 过滤器可以用在两个地方&#xff1a…