统一网关 Gateway【微服务】
文章目录
- 1. 前言
- 2. 搭建网关服务
- 3. 路由断言工厂
- 4. 路由过滤器
- 4.1 普通过滤器
- 4.2 全局过滤器
- 4.3 过滤器执行顺序
- 5. 跨域问题处理
1. 前言
通过前面的学习我们知道,通过 Feign 就可以向指定的微服务发起 http 请求,完成远程调用。但是这里有一个问题,我的微服务好像谁来都可以访问,这样会不会不安全?那是肯定的。
实际生产中,有很多的业务模块只有我们内部的人才能用,不是谁都能访问,这时候我们就需要对用户的身份进行验证,而这个验证的工作就是网关(Gateway)来完成的。
一切请求一定要先到网关,再到微服务,其实是对微服务的一种保护措施。
(1)网关功能:
① 身份认证和权限校验(认证通过后,再将请求转发到对应的微服务)
② 服务路由(根据请求信息判断应该将请求转发到哪个微服务)
③ 负载均衡(对外的服务也会有多个实例,需要做负载均衡)
④ 请求限流(限制微服务的用户请求量)
注意 Ribbon 是对内部的 userserver 做负载均衡,而网关是对外部的 orderserver 做负载均衡!
(2)网关的技术实现:
① gataway(新技术,响应式编程,非阻塞式,性能好,吞吐能力强)
② zuul(较早的技术,基于 Servlet,阻塞式,性能差)
2. 搭建网关服务
① 创建新的 module,引入 SpringCloudGateway 的依赖和 Nacos 的服务发现依赖
<dependencies><!--nacos服务注册发现依赖--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--网关gateway依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency>
</dependencies>

② 创建启动类


③ 编写路由配置及 Nacos 地址,路由配置由三部分组成:路由 id、目标地址和路由断言(路由断言其实就是匹配规则)
路由断言:判断请求是否符合要求,符合则转发到路由目的地。
server:port: 10010 #网关端口
spring:application:name: gateway #服务名称cloud:nacos:server-addr: localhost:8848 #nacos地址gateway:routes: #网关路由配置- id: user-server #路由id,自定义,只要唯一即可uri: lb://userserver #路由的目标地址,lb就是负载均衡,后面跟服务名predicates: #路由断言,也就是判断请求是否符合路由规则的条件- Path=/user/** #只要以/user/开头就符合要求- id: order-serveruri: lb://orderserverpredicates:- Path=/order/**

路由不止一个,用 - 来表示路由数组!
④ 依赖冲突报错
如果你的 spring-boot-starter-web 依赖是写到父工程里的,那么不出意外的话启动 GatewayApplication 时将会报错:

翻译过来就是 SpringMVC 的依赖冲突了,SpringCloudGateway 的内部是通过 netty+webflux 实现的,而 webflux 实现和 SpringMVC 的配置依赖是有冲突的。
解决办法有两种:
第一种就是去除父工程中的 spring-boot-starter-web 这个依赖, 然后在各个子工程需要的地方进行单独引入依赖即可;
第二种就是在 pom.xml 中进行修改,用以下依赖替换原来的 spring cloud gateway。
<!--网关gateway依赖-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></exclusion><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></exclusion></exclusions>
</dependency>
⑤ 启动项目测试一下,访问 http://localhost:10010/order/2


整体流程:
用户发起 http://localhost:10010/user/2 请求,接着该请求进入网关,而网关是无法处理具体业务的,所以它会基于路由规则去做判断,然后代理到具体的服务上去处理业务。
上面步骤中我们定义了两个路由规则,以 user 开头的路径将会被代理到 userserver 服务,接着网关会拿着服务名(userserver)去找 Nacos 拉取服务列表,然后做一个负载均衡,发送请求 http://localhost:10010/user/2。
网关只是负责检验并转发请求,而最终处理业务的是具体的服务!
3. 路由断言工厂
我们在配置文件中写的断言规则只是字符串,这些字符串会被断言工厂读取并处理,最终转变为路由判断的条件。
Spring 提供了 11 种基本的 Predicate 工厂:

Path 是我们用的最多的方式!
测试一下,时间设在 2031 年之后才可以访问,所以现在肯定是不能访问的:
只有当断言规则都满足的时候才能访问成功,路径符合,但时间不符合,照样不能访问。


4. 路由过滤器
4.1 普通过滤器
GatewayFilter 是网关中提供的一种过滤器,可以处理进入网关的请求,以及微服务返回的响应。
路由之后并不是立即向微服务发起请求的,其实我们还可以给路由配置各种各样的过滤器,这些过滤器最终会形成一个过滤器链,对进入网关的请求做各种处理。
请求给了微服务,微服务处理完之后会返回一个结果,这个结果也是先到达网关,网关同样会通过过滤器逐层处理这个响应结果,最终返回给用户。
断言匹配成功相当于请求通过了网关的大门,然后过滤器会对请求做一些处理(比如添加请求头、请求参数等),最后网关会将处理好的请求代理到具体的服务,做业务处理。

Spring 提供了 31 种不同的路由过滤器工厂:

做一个测试,我们可以在 Controller 中获取一下请求头,并在控制台输出:


如果要对所有的路由都生效,则可以将过滤器工厂写到 default-filters 中,与 routes 处于同一级:

4.2 全局过滤器
全局过滤器即自定义过滤器,全局过滤器的作用也是处理一切进入网关的请求和微服务响应,与 GatewayFilter 的作用一样。区别在于 GatewayFilter 通过配置定义,处理逻辑是固定的,而 GlobalFilter 的逻辑需要自己写代码实现, 定义方式是实现 GlobalFilter 接口。
做一个案例,定义全局过滤器拦截请求,判断请求的参数是否满足下面两个条件:
① 参数中是否有 authorization;
② authorization 的参数值是否为 admin。
如果同时满足则放行,否则拦截。
① 创建 AuthorizeFilter 类,实现 GlobalFilter 接口,并重写 filter 方法


第一个参数用于处理业务逻辑,第二个参数是用来放行的,把请求委托给下一个过滤器去处理,其实就是调用下一个过滤器的 filter 方法,等同于放行。
② 编写核心代码
过滤器之间是有先后执行顺序的,这个我们可以通过注解的方式设置,也可以通过实现 Ordered 接口的方式来设置,数值越小,优先级越高!
package com.zxe.gateway;import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;//定义过滤器执行的顺序,数值越小优先级越高
//可以通过注解设置,也可以通过实现Ordered接口来设置
//@Order(-1)
@Component
public class AuthorizeFilter implements GlobalFilter, Ordered {@Override
// exchange请求上下文,里面可以获取Request、Response等信息
// chain用来把请求委托给下一个过滤器
// return表示当前过滤器业务结束public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//1.获取请求参数ServerHttpRequest request = exchange.getRequest();MultiValueMap<String, String> params = request.getQueryParams();//2.获取参数中的authorization参数String auth = params.getFirst("authorization");//3.判断参数是否等于adminif ("admin".equals(auth)) {//4.等于admin放行,其实是调用下一个过滤器的filter方法,等同于放行return chain.filter(exchange);}//5.不等于就拦截,后面的业务不会再继续,我们一般会设置状态码返回给用户,提示未登录exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);return exchange.getResponse().setComplete();}//定义过滤器执行的顺序,数值越小优先级越高@Overridepublic int getOrder() {return -1;}
}

③ 重启项目,我们可以在请求路径中携带 authorization 参数测试一下,无 authorization 参数或参数值不正确的一律被拦截,只有当 authorization = admin 时才会被放行


整体流程:
① 用户请求进入网关,断言匹配失败,报 404 错误,匹配成功直接将请求送入过滤器链;
② 过滤器分为普通过滤器和自定义过滤器,普通过滤器可以在配置文件中设置,自定义过滤器需要实现 GlobalFilter 接口,它可以处理更复杂的过滤业务;
③ 过滤不通过的请求就会被拦截,报401错误,只有层层过滤都通过了,请求才会被路由到具体的服务上,处理具体的业务。
4.3 过滤器执行顺序
请求进入网关会碰到三类过滤器:当前路由过滤器、默认过滤器和全局过滤器。
查看当前路由过滤器和默认过滤器的源码知道,它们的过滤器工厂首先会读取配置文件,然后生成一个真正的过滤器 GatewayFilter。再看全局过滤器的源码,可以看到 GlobalFilter 其实是被 GatewayFilterAdapter 适配到 GatewayFilter 的,也就是说网关中所有的过滤器都是 GatewayFilter 类型的。既然是同一种类型,那么就可以把它们放到同一个集合里面去排序。
所以请求路由后,会将当前路由过滤器和默认过滤器、全局过滤器合并到一个过滤器链(集合)中,排序后依次执行每个过滤器。
每个过滤器都必须指定一个 int 类型的 order 值,order 值越小,优先级越高,执行顺序就越靠前。
GlobalFilter 通过实现 Ordered 接口,或者添加 @Order 注解来指定 order 值,过滤器的执行顺序由我们自己指定。而当前路由过滤器和默认过滤器的执行顺序是由 Spring 指定的,默认按照声明顺序从 1 开始递增,这里需要注意的是当前路由过滤器和默认过滤器是分开计数的,这就会出现计数冲突的问题(比如都是 1)。
源码里面的默认过滤器是先加载的,然后再加载当前路由过滤器,最后加载全局过滤器,组织过滤器链。所以,当过滤器的 order 值一样时,会按照 默认过滤器 > 当前路由过滤器 > 全局过滤器的顺序执行。
5. 跨域问题处理
域名不一致就是跨域,主要包括:
① 域名不同:www.taobao.com 和 www.taobao.org 和 www.jd.com 和 miaosha.jd.com
② 域名相同,端口不同。localhost:8080 和 localhost:8081
跨域问题:浏览器禁止请求的发起者与服务端发生跨域 ajax 请求,请求被浏览器拦截。
网关处理跨域采用的是 CORS 方案,CORS的底层逻辑网关其实已经帮我们做好了,我们只需要简单的配置即可实现。
spring:cloud:gateway:globalcors: #全局的跨域处理add-to-simple-url-handler-mapping: true #解决options请求被拦截的问题cors-configurations:'[/**]':allowedOrigins: #允许哪些网站的跨域请求- "http://localhost:8090"- "http://www.leyou.com"allowedMethods: #允许的跨域ajax的请求方式- "GET"- "POST"- "DELETE"- "PUT"- "OPTIONS"allowedHeaders: "*" #允许在请求中携带的头信息allowCredentials: true #是否允许携带cookiemaxAge: 360000 #这次跨域检测的有效期
相关文章:
统一网关 Gateway【微服务】
文章目录 1. 前言2. 搭建网关服务3. 路由断言工厂4. 路由过滤器4.1 普通过滤器4.2 全局过滤器4.3 过滤器执行顺序 5. 跨域问题处理 1. 前言 通过前面的学习我们知道,通过 Feign 就可以向指定的微服务发起 http 请求,完成远程调用。但是这里有一个问题&am…...
【征服redis1】基础数据类型详解和应用案例
博客计划 ,我们从redis开始,主要是因为这一块内容的重要性不亚于数据库,但是很多人往往对redis的问题感到陌生,所以我们先来研究一下。 本篇,我们先看一下redis的基础数据类型详解和应用案例。 1.redis概述 以mysql为…...
【WPF.NET开发】WPF中的XAML资源
本文内容 使用 XAML 中的资源静态和动态资源静态资源动态资源样式、DataTemplate 和隐式键 资源是可以在应用中的不同位置重复使用的对象。 资源的示例包括画笔和样式。 本概述介绍如何使用 Extensible Application Markup Language (XAML) 中的资源。 你还可以使用代码创建和…...
ChatGPT 淘金潮(全)
原文:The ChatGPT GoldRush 译者:飞龙 协议:CC BY-NC-SA 4.0 一、ChatGPT 简介 什么是 ChatGPT? ChatGPT 是由 OpenAI 基于 GPT-4 架构创建的大型语言模型。它旨在理解和回应自然语言文本输入,使得可以与机器进行对话…...
【零基础入门Python数据分析】Anaconda3 JupyterNotebookseaborn版
目录 一、安装环境 python介绍 anaconda介绍 jupyter notebook介绍 anaconda3 环境安装 解决JuPyter500:Internal Server Error问题-CSDN博客 Jupyter notebook快捷键操作大全 二、Python基础入门 数据类型与变量 数据类型 变量及赋值 布尔类型与逻辑运算…...
C++面试:单例模式、工厂模式等简单的设计模式 创建型、结构型、行为型设计模式的应用技巧
理解和能够实现基本的设计模式是非常重要的。这里,我们将探讨两种常见的设计模式:单例模式和工厂模式,并提供一些面试准备的建议。 目录 单例模式 (Singleton Pattern) 工厂模式 (Factory Pattern) 面试准备 1. 理解设计模式的基本概念…...
Oracle JDK 8 中的 computeIfAbsent 方法及实践
Java 8 引入了一系列新特性,其中之一是对 Map 接口的增强,其中包括了 computeIfAbsent 方法。这个方法为处理映射提供了一种便捷而强大的方式,允许在键不存在或对应的值为 null 时,动态计算新的值并将其放入映射。在本篇博客中&am…...
华为设备vlan下配置MSTP,STP选举
核心代码,不同实例,承载不同流量,为每个实例设置一个根网桥达到分流的效果 stp region-config //进入stp区域的设置 region-name R1 //区域命名为R1 instance 1 vlan 10 …...
案例学Python:filter()函数的用法,高级!
大家好,这里是程序员晚枫,又来分享有用的Python知识了。 Python之所以好用,是因为有大量用于科学计算的内置函数和第三方库。用好这些第三方库,可以显著提高我们编程的速度和质量。 今天我们一起来看一下Python中一个重要的内置…...
jmeter--7.BeanShell
目录 1. beanshell常用语法 1.1 log:日志写入 1.2 vars:设置和引用局部变量(同线程组) 1.3 props:设置和引用全局变量(跨线程组) 1.4 prev:获取前一个请求返回的信息 2. beans…...
第 3 场 蓝桥杯小白入门赛 解题报告 | 珂学家 | 单调队列优化的DP + 三指针滑窗
前言 整体评价 T5, T6有点意思,这场小白入门场,好像没真正意义上的签到,整体感觉是这样。 A. 召唤神坤 思路: 前后缀拆解 #include <iostream> #include <algorithm> #include <vector> using namespace std;int main()…...
debian apt 装 mysql8
MySQL :: MySQL 8.0 参考手册 :: 2.5.5 使用来自 Oracle 的 Debian 软件包在 Linux 上安装 MySQL apt install -f lsb-release gnupg wget https://repo.mysql.com//mysql-apt-config_0.8.29-1_all.deb dpkg -i mysql-apt-config…...
LeetCode 每日一题 Day 37-43
终于考完试了,寒假期间将会每天持续更新! 447. 回旋镖的数量(Day 37) 给定平面上 n 对 互不相同 的点 points ,其中 points[i] [xi, yi] 。回旋镖 是由点 (i, j, k) 表示的元组 ,其中 i 和 j 之间的欧式距离和 i 和 k 之间的欧…...
产品百度百科怎么创建?产品如何上百度百科?
百度百科作为一个权威的信息平台,承载着巨大的流量和曝光度。对于一个产品来说,能够在百度百科上拥有一席之地,无疑是一种极高的荣誉,同时也是提升品牌知名度、增加信任度的重要手段。产品百度百科不仅能够详细、全面地介绍产品信…...
Vue keep-alive的使用和原理解析
✨ 专栏介绍 在当今Web开发领域中,构建交互性强、可复用且易于维护的用户界面是至关重要的。而Vue.js作为一款现代化且流行的JavaScript框架,正是为了满足这些需求而诞生。它采用了MVVM架构模式,并通过数据驱动和组件化的方式,使…...
Fine-tuning:个性化AI的妙术
在本篇文章中,我们将深入探讨Fine-tuning的概念、原理以及如何在实际项目中运用它,以此为初学者提供一份入门级的指南。 一、什么是大模型 ChatGPT大模型今年可谓是大火,在正式介绍大模型微调技术之前,为了方便大家理解,我们先对大模型做一个直观的抽象。 本质上,现在…...
说清楚Kubernetes、Docker、Dockershim、Containerd、runC、CRI、OCI的关系
Kubernetes v1.20版本 的 release note 里说 deprecated docker。并且在后续版本 v1.24 正式删除了 dockershim 组件,这对我们有什么影响呢?Kubernetes 1.20: The Raddest Release | Kubernetes 为了搞明白这件事情,以及理解一系列容器名词 …...
x-cmd pkg | trash-cli - 类 Unix 系统的命令行垃圾桶
目录 简介首次用户技术特点竞品和相关作品进一步阅读 简介 trash-cli 是类 Unix 系统的命令行垃圾桶,用于移动文件到回收站,同时会记录文件的原地址和删除日期。 该工具使用与 GNOME、KDE 和 XFCE 等桌面环境相同的垃圾桶,所以即使是非 …...
基于Java+SpringBoot+vue实现图书借阅和销售商城一体化系统
基于JavaSpringBootvue实现图书借阅和销售商城一体化系统 🍅 作者主页 央顺技术团队 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 🍅 文末获取源码联系方式 📝 🍅 查看下方微信号获取联系方式 承接各种定制系…...
集成xxljob项目如何迁移到K8S
前言 大家好,今天我们将基于XXL-Job,探讨任务调度迁移到云端的相关话题。 XXL-Job是一款功能强大、易用可靠的国产分布式任务调度平台,是目前国内使用比较广泛的分布式任务调度平台之一。它的主要特点包括: 支持分布式、多线程…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
uniapp 小程序 学习(一)
利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 :开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置,将微信开发者工具放入到Hbuilder中, 打开后出现 如下 bug 解…...
算术操作符与类型转换:从基础到精通
目录 前言:从基础到实践——探索运算符与类型转换的奥秘 算术操作符超级详解 算术操作符:、-、*、/、% 赋值操作符:和复合赋值 单⽬操作符:、--、、- 前言:从基础到实践——探索运算符与类型转换的奥秘 在先前的文…...
jdbc查询mysql数据库时,出现id顺序错误的情况
我在repository中的查询语句如下所示,即传入一个List<intager>的数据,返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致,会导致返回的id是从小到大排列的,但我不希望这样。 Query("SELECT NEW com…...
