服务网关工作原理,如何获取用户真实IP?
文章目录
- 一、什么是网关
- 二、网关工作原理 (★)
- 三、SpringCloud Gateway
- 3.1 Gateway 简介
- 3.2 Gateway 环境搭建
- 3.3 自定义路由规则 (★)
- 3.4 局部过滤器
- 3.5 全局过滤器(案例:获取用户真实IP地址) (★)
- 补充1:不同类型的客户端如何设置网关
- 补充2:多个全局多滤器的执行优先级
- 补充3:局部过滤器和全局过滤器的执行优先级
一、什么是网关
在微服务架构中,⼀个系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢?如果没有网关的存在,我们只能在客户端记录每个微服务的地址,然后分别去调用。

这样的架构,会存在着诸多的问题:
- 客户端多次请求不同的微服务,增加客户端代码或配置编写的复杂性。
- 认证复杂,每个服务都需要独立认证。
- 微服务做集群的情况下,客户端并没有负载均衡的功能。
上面的这些问题可以借助 API 网关来解决。
API 网关指系统的统一入口,它封装了应用程序的内部结构,为客户端提供统⼀服务,⼀些与业务本身功能无关的公共逻辑可以在这里实现,如:认证、鉴权、监控、路由转发等等。
添加上 API 网关之后,系统的架构图变成了如下所示:

二、网关工作原理 (★)
网关本身也是个微服务,服务注册中心以后,将注册中心的服务列表拉取到本地缓存,并配置相应的路由规则,如下图所示:

网关组件提供统一请求入口,可以进行统一逻辑的处理,并提供网络隔离的能力(即请求只能通过网关来访问,不能通过某一个服务的IP地址绕过网关来访问)。
当浏览器发起请求http://192.168.10.115/product-serv/product/1,
step1:网关获取到请求地址,默认截取域名后面的部分请求路径 /product-serv/product/1
step2:拿到路径信息和路由规则进行匹配,可以获取到对应的服务名product-service
step3:拿到服务名在本地的缓存列表中找到对应的IP地址列表,基于 Ribbon 实现负载均衡算法得出 IP 地址。
step4:进行 URL 地址拼接 http://192.168.10.110/product/1,最终进行网络的调用。
三、SpringCloud Gateway
3.1 Gateway 简介
Spring Cloud Gateway 是 Spring 公司基于Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供⼀种简单有效的统⼀的 API 路由管理方式。它的目标是替代 Netflflix Zuul,其不仅提供统⼀的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控和限流。
Spring Cloud Gateway 存在诸多优点,如:性能强劲、功能强大、易扩展,其内置了很多实用的功能,例如转发、监控、限流等。但也存在缺点,如:不能将其部署在 Tomcat、Jetty 等 Servlet 容器里,只能打成 jar 包执行,需要 Spring Boot 2.0及以上的版本才支持等。
3.2 Gateway 环境搭建
1、创建一个 api-gateway 的模块,导入相关依赖:
<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/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.axy</groupId><artifactId>shop-parent</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>api-gateway</artifactId><name>api-gateway</name><dependencies><!--gateway⽹关--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!--nacos客户端--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>...</dependencies><build><finalName>api-gateway</finalName></build>
</project>
2、编写启动类
@SpringBootApplication
@EnableDiscoveryClient
public class ApiGateWayServer {public static void main(String[] args) {SpringApplication.run(ApiGateWayServer.class, args);}
}
3、编写配置⽂件
server:port: 9000
spring:application:name: api-gatewaycloud:nacos:discovery:server-addr: localhost:8848gateway:discovery:locator:enabled: true # 让gateway可以发现nacos中的微服务
注:spring.cloud.gateway.discovery.locator.enabled=true 的作用是让 Gateway 开启服务注册和发现的功能,并且为每一个微服务创建一个默认的路由,该路由将以服务名开头的请求路径转发到对应的服务。如:/product-service/** 转发到 product-service 的服务下。
4、启动测试

3.3 自定义路由规则 (★)
gateway 提供了默认的路由规则,但也支持自定义规则,具体属性如下:
① id:路由标识符,区别于其他 Route。
② uri:路由指向的目的地 uri,即客户端请求最终被转发到的微服务
③ order:用于多个 Route 之间的排序,数值越小排序越靠前,匹配优先级越高
④ predicate:断言的作用是进行条件判断,只有断言都返回真,才会真正的执行路由
⑤ filters:过滤器用于修改请求和响应信息
server:port: 9000
spring:application:name: api-gatewaycloud:nacos:discovery:server-addr: localhost:8848gateway:discovery:locator:enabled: true # 让gateway可以发现nacos中的微服务routes: # 自定义路由配置- id: product_route # 路由名称,保证唯一uri: lb://product-service # 将符合条件的请求转发到哪个微服务,lb表示对服务进行负载均衡predicates: # 拦截哪些请求- Path=/product-serv/**filters: # 前台访问:http://localhots:9000/product-service/product/1 去掉第一层以后路径以后,http://product-service/product/1- StripPrefix=1 # 在转发请求之前,将拦截到的第一层路径删除掉- id: order_routeuri: lb://order-servicepredicates:- Path=/order-serv/**filters:- StripPrefix=1
注:StripPrefix=1 表示在请求转发请求之前,将拦截到的第一层路径删除掉。
如:前台访问http://localhots:9000/product-service/product/1 去掉第一层以后路径以后变成 http://product-service/product/1
启动测试:

3.4 局部过滤器
局部过滤器是针对单个路由(或者单个服务)的过滤器,用以添加针对某一个服务的独立功能。下面以需求的形式讲解一下如何配置局部过滤器。
需求:统计订单服务调用耗时。
编写Filter类,注意名称是有固定格式 xxxGatewayFilterFactory。如下面设置 filters 的属性 Time=true,则编写局部过滤器的类名为 TimeGatewayFilterFactory。

继承 AbstractGatewayFilterFactory<TimeGatewayFilterFactory.Config> 类,其中 Config 类是该类的内部类用于承接配置文件中配置的值,重写 shortcutFieldOrder、apply 两个方法。
/*** 局部过滤器*/
@Component
public class TimeGatewayFilterFactory extends AbstractGatewayFilterFactory<TimeGatewayFilterFactory.Config> {public TimeGatewayFilterFactory() {super(Config.class);}// 读取配置⽂件中的参数赋值到配置类 Config 中@Overridepublic List<String> shortcutFieldOrder() {return Arrays.asList("show");}// 拦截到之后就会调用 apply 方法,把创建对象时候反射创建出来的 Config 传入进来@Overridepublic GatewayFilter apply(Config config) {return new GatewayFilter() {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 前置的逻辑if (!config.show) {return chain.filter(exchange);}System.out.println("前置逻辑");long start = System.currentTimeMillis();// exchange相当于requestreturn chain.filter(exchange).then(Mono.fromRunnable(() -> {long end = System.currentTimeMillis();System.out.println("请求耗时:" + (end - start));// 后置的逻辑System.out.println("后置逻辑");}));}};}@Setter@Getterstatic class Config {private boolean show;}
}
注:其中 Config 作为内部类,是通过反射将配置文件里面的值设置到对应的属性上。如:配置文件中配置 Time=true,则 show 的值最终为 true。另外, shortcutFieldOrder() 方法的返回值是数组,其用于指定反射时的设置顺序。
如假设:配置文件Time=true,1,hello ,那么 Config 的设置应该有三个值,并且属性名与shortcutFieldOrder() 返回值的数组元素的 “名称” 一一对应,如下:
@Component
public class TimeGatewayFilterFactory extends AbstractGatewayFilterFactory<TimeGatewayFilterFactory.Config> {public TimeGatewayFilterFactory() {super(Config.class);}// 读取配置⽂件中的参数赋值到配置类 Config 中@Overridepublic List<String> shortcutFieldOrder() {return Arrays.asList("show", "xx", "yy");}...@Setter@Getterstatic class Config {private boolean show;private Long xx;private String yy;}
}
访问订单服务的时候打印时间如下:

3.5 全局过滤器(案例:获取用户真实IP地址) (★)
全局过滤器作用于所有路由,无需配置文件配置。通过全局过滤器可以实现对权限的统⼀校验,安全性验证等功能。下面以需求的形式讲解一下如何配置局部过滤器:
需求:实现统⼀鉴权的功能,需要在网关判断请求中是否包含token,如果有则还需要在请求头中设置用户的IP地址,则执行正常逻辑。实现代码如下:
/*** 全局过滤器*/
@Component
public class AuthGlobalFilter implements GlobalFilter {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {System.out.println("全局过滤器前置过滤器");// 获取到请求中的token信息,验证token是否有效,如果无效拦截请求String token = exchange.getRequest().getQueryParams().getFirst("token");if (StringUtils.isEmpty(token) || !"123".equals(token)) {System.out.println("鉴权失败");exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);return exchange.getResponse().setComplete();}ServerHttpRequest request = exchange.getRequest().mutate().header("REAL_IP", exchange.getRequest().getRemoteAddress().getHostString()).build();return chain.filter(exchange.mutate().request(request).build()).then(Mono.fromRunnable(new Runnable() {@Overridepublic void run() {System.out.println("全局过滤器后置过滤器");}}));}
}
这里解释以下,为何要在网关获取用户的地址,因为当请求通过网关转发到微服务后使用 Request.getRomteAddr()获取到的只是网关的地址,因此需要在网关侧获取真实IP。

另外:鉴权逻辑一般放在拦截器中实现,后面将会详细说明。
补充1:不同类型的客户端如何设置网关
由于不同类型客户端访问微服务时,有些公共逻辑会存在差异,如:第三方访问时有限流的操作等。因此建议针对不同端,设置不同的网关。

补充2:多个全局多滤器的执行优先级
多个全局多滤器最终都是通过Order值进行排序执行,Order值越小越先执行。
两个全局过滤器Order值相同时,根据文件名字母排序,文件名靠前的优先更高。原因是包扫描时是按照文件的顺序扫描的,然后封装到List集合的,通过Order值排序时如果Order值相同,文件名在前名的依然会排在前面。
但也可以实现Ordered接口,重写 getOrder() 方法,以 Order 进行排序,Order 越小优先级越高。
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {...}@Overridepublic int getOrder() {return 2;}
}
补充3:局部过滤器和全局过滤器的执行优先级
多滤器最终都是通过Order值进行排序执行,Order值越小越先执行。
全局过滤器和局部过滤器Order值相同时,GlobalFilter类型优先更高。
原因是这两种过滤器最终会合并到一个过滤器集合中形成过滤器调用链,源码是通过 list.addAll(); 方法将局部过滤器加到了全局过滤器集合中,addAll()是末尾添加方式,所以 Order 值相同时局部过滤器会排在后面。
参考:https://blog.csdn.net/Anenan/article/details/114691488
文章参考:Java微服务商城高并发秒杀项目实战|Spring Cloud Alibaba真实项目实战+商城双11秒杀+高并发+消息+支付+分布式事物Seata
相关文章:
服务网关工作原理,如何获取用户真实IP?
文章目录 一、什么是网关二、网关工作原理 (★)三、SpringCloud Gateway3.1 Gateway 简介3.2 Gateway 环境搭建3.3 自定义路由规则 (★)3.4 局部过滤器3.5 全局过滤器(案例:获取用户真实IP地址) (★) 补充1:不同类型的客户端如何设…...
单链表的实现(C语言)
目录 1.单链表 1.1 实现单链表 1.1.1 文件创建 1.1.2 链表功能了解 1.1.3 链表的结点 1.1.4 链表的函数声明 1.1.5 链表功能的实现 链表是一种链式结构,物理结构不连续,逻辑结构是连续的,在计算机中链表的实际存储是按照一个结点内存放…...
sql语句的训练2024/9/9
1题 需要看清思路:不是将数据库中的device_id的名字改为user_infors_example,而是在查找的时候,需要将device_id看成user_infors_example来进行查找。 答案 select device_id AS user_infos_example FROM user_profile limit 2 2 当固定查找…...
【QT】常用控件-下
欢迎来到Cefler的博客😁 🕌博客主页:折纸花满衣 🏠个人专栏:QT 目录 👉🏻QComboBox👉🏻 QSpinBox👉🏻QDateTimeEdit👉🏻QD…...
828华为云征文|华为云Flexus X实例docker部署Jitsi构建属于自己的音视频会议系统
828华为云征文|华为云Flexus X实例docker部署Jitsi构建属于自己的音视频会议系统 华为云最近正在举办828 B2B企业节,Flexus X实例的促销力度非常大,特别适合那些对算力性能有高要求的小伙伴。如果你有自建MySQL、Redis、Nginx等服务的需求&a…...
25虾皮笔试shopee笔试测评sea笔试测评题型
虾皮笔试shopee笔试测评用的自己的笔试系统,全英文笔试: 1.Numerical Reasoning Test:10题,言语推断和数学计算 2. Verbal Reasoning Test:10题,言语理解,每题一段英文材料,选对错…...
启明云端乐鑫代理商,乐鑫ESP32无线芯片方案,物联网设备WiFi联动控制
随着智能和远程技术的飞速发展,物联网(IoT)逐渐出现在我们生活的每一个角落。乐鑫以其创新的无线通信技术,正成为智能家居、工业自动化和医疗设备等领域的推动者。 无线WiFi芯片模组不仅提供了强大的数据处理能力,还赋予了设备以直观的交互方…...
希尔排序/选择排序
前言: 本篇主要对常见的排序算法进行简要分析,代码中均以数组 arr[] { 5, 3, 9, 6, 2, 4, 7, 1, 8 } 为例,进行升序排列。 常见的排序算法有如下: 选择排序中,直接选择排序没有任何实际与教育意义,而堆排…...
漫谈设计模式 [16]:中介者模式
引导性开场 菜鸟:老鸟,我最近在开发一个聊天应用的时候遇到了点问题。每个用户都需要与其他用户直接通信,这让我在代码中写了很多复杂的逻辑来管理这些联系。这样下去,代码越来越难维护了。你有什么建议吗? 老鸟&…...
深度学习-物体检测YOLO(You only look once)
目录 一:YOLO算法的网络结构 流程 1.图像分割 2.图片在网格中的处理 3.非极大值抑制 二:训练 三:分类误差 四:与Faster R-CNN对比 一:YOLO算法的网络结构 GooleNet4个卷积2个全连接层 流程 输入原始图片resize到…...
redisson中的分布式锁
我的博客大纲 我的后端学习大纲 a.redisson概述: 1.Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)2.redisson介绍官方文档地址:3.Redisson它不仅提供了一系列的分布式的Java常用对象,还…...
如何将镜像推送到docker hub
前言 这一篇应该是最近最后一篇关于docker的博客了,咱来个有始有终,将最后一步——上传镜像给他写完,废话不多说,直接进入正题。 登录 首先需要确保登录才能推送到你的仓库中去,在终端输入docker login,输入用户名和…...
GO 匿名函数
GO 匿名函数 文章目录 GO 匿名函数1. **回调函数**2. **goroutine 中的操作**3. **延迟操作(defer)**4. **内联处理逻辑**5. **闭包**6. **过滤、映射等函数式编程风格**7. **测试中的临时逻辑**8. **短期存在的逻辑操作**总结 匿名函数在 Go 语言中的使…...
JuiceFS 在多云架构中加速大模型推理
在大模型的开发与应用中,数据预处理、模型开发、训练和推理构成四个关键环节。本文将重点探讨推理环节。在之前的博客中,社区用户 BentoML 和贝壳的案例提到了使用 JuiceFS 社区版来提高模型加载的效率。本文将结合我们的实际经验,详细介绍企…...
【DCL】Dual Contrastive Learning for General Face Forgery Detection
文章目录 Dual Contrastive Learning for General Face Forgery Detectionkey points:贡献方法数据视图生成对比学习架构实例间对比学习实例内对比学习总损失函数实验实验细节定量结果跨数据集评估跨操作评估消融实验可视化Dual Contrastive Learning for General Face Forgery…...
https的特点
https的特点 优点:缺点:HTTPS是如何保证安全的? 优点: 使用HTTPS协议可以认证用户和服务器,确保数据发送到正确的客户端和服务器;使用HTTPS协议可以进行加密传输、身份认证,通信更加安全、防止…...
〖open-mmlab: MMDetection〗解析文件:mmdet/models/losses/cross_entropy_loss.py
目录 深入解析MMDetection中的CrossEntropyLoss及其应用1. 概述2. 核心函数2.1 cross_entropy2.1.1 函数定义和参数说明2.1.2 函数体2.1.3 总结 2.2 binary_cross_entropy2.2.1 _expand_onehot_labels函数2.2.2 binary_cross_entropy函数2.2.3 总结 2.3 mask_cross_entropy2.3.…...
【PyTorch单点知识】torch.nn.Embedding模块介绍:理解词向量与实现
文章目录 0. 前言1. 基础介绍1.1 基本参数1.2 可选参数1.3 属性1.4 PyTorch源码注释 2. 实例演示3. embedding_dim的合理设定4. 结论 0. 前言 按照国际惯例,首先声明:本文只是我自己学习的理解,虽然参考了他人的宝贵见解及成果,但…...
Jedis 操作 Redis 数据结构全攻略
Jedis 操作 Redis 数据结构全攻略 一 . 认识 RESP二 . 前置操作2.1 创建项目2.2 关于开放 Redis 端口的问题2.2.1 端口转发?2.2.2 端口配置 2.3 连接到 Redis 服务器 三 . 通用命令3.1 set 和 get3.2 exists 和 del3.3 keys3.4 expire、ttl、type 三 . string 相关命令3.1 mse…...
ctf.show靶场ssrf攻略
前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 web351 解析:post传入url参数他就会访问。 解法: hackbar传入url参数写入https://127.0.0.1/flag.php web352 解析:post传入url参数,不能是127.0.0.1和localhost 解法:缩写127.1传入 web353 解析…...
【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文通过代码驱动的方式,系统讲解PyTorch核心概念和实战技巧,涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...
算法打卡第18天
从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 示例 1: 输入:inorder [9,3,15,20,7…...
AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...
【1】跨越技术栈鸿沟:字节跳动开源TRAE AI编程IDE的实战体验
2024年初,人工智能编程工具领域发生了一次静默的变革。当字节跳动宣布退出其TRAE项目(一款融合大型语言模型能力的云端AI编程IDE)时,技术社区曾短暂叹息。然而这一退场并非终点——通过开源社区的接力,TRAE在WayToAGI等…...
起重机起升机构的安全装置有哪些?
起重机起升机构的安全装置是保障吊装作业安全的关键部件,主要用于防止超载、失控、断绳等危险情况。以下是常见的安全装置及其功能和原理: 一、超载保护装置(核心安全装置) 1. 起重量限制器 功能:实时监测起升载荷&a…...
