微服务-Gateway
案例搭建
官网地址

父Pom
<com.alibaba.cloud.version>2.2.8.RELEASE</com.alibaba.cloud.version>
<com.cloud.version>Hoxton.SR12</com.cloud.version>
<com.dubbo.version>2.2.7.RELEASE</com.dubbo.version>
<dependencyManagement><dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>${com.alibaba.cloud.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${com.cloud.version}</version><type>pom</type><scope>import</scope></dependency><!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-dubbo --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-dubbo</artifactId><version>${com.dubbo.version}</version></dependency></dependencies></dependencyManagement>
工程POM
<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>
server:port: 9005
spring :application:name: gateway-servercloud:nacos:discovery:server-addr: ip:8848gateway:routes:- id: gateway-provideruri: http://127.0.0.1:8088predicates:- Path=/provider/**filters:- StripPrefix=1- id: gateway-consumeruri: http://127.0.0.1:8089predicates:- Path=/consumer/** filters:- StripPrefix=1 #转发之前将路径前面的一个字符串去除 比如/consumer/echo 最终转发到服务是 http://127.0.0.1:8089/echo- id: gateway-lburi: lb://openfeign-provider #负载均衡,填写nacos里面的服务名称predicates:- Path=/lb/**filters:- StripPrefix=1
启动一个普通的服务端和消费端,另外起一个有三台服务的集群,这些节点的搭建比较容易,可以看同目录笔记。
怎么做到负载均衡?怎么探索源码找到负载均衡?
org.springframework.cloud.gateway.filter.LoadBalancerClientFilter
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {URI url = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);String schemePrefix = exchange.getAttribute(GATEWAY_SCHEME_PREFIX_ATTR);if (url == null|| (!"lb".equals(url.getScheme()) && !"lb".equals(schemePrefix))) {return chain.filter(exchange);}// preserve the original urladdOriginalRequestUrl(exchange, url);if (log.isTraceEnabled()) {log.trace("LoadBalancerClientFilter url before: " + url);}// 选择实例final ServiceInstance instance = choose(exchange);if (instance == null) {throw NotFoundException.create(properties.isUse404(),"Unable to find instance for " + url.getHost());}URI uri = exchange.getRequest().getURI();// if the `lb:<scheme>` mechanism was used, use `<scheme>` as the default,// if the loadbalancer doesn't provide one.String overrideScheme = instance.isSecure() ? "https" : "http";if (schemePrefix != null) {overrideScheme = url.getScheme();}// 选择好节点以后重新组织请求URIURI requestUrl = loadBalancer.reconstructURI(new DelegatingServiceInstance(instance, overrideScheme), uri);if (log.isTraceEnabled()) {log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);}exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);return chain.filter(exchange);}
自定义拦截
首先看官方网提供的几种断言,都是比较简单的这里不在演示:
官网地址
源码,这些类提供了这些能力:

自定义局部
自定义类,这个类可以参考DedupeResponseHeaderGatewayFilterFactory进行定义
@Component
public class CostGatewayFilterFactory extendsAbstractGatewayFilterFactory<CostGatewayFilterFactory.CustomConfig> {public CostGatewayFilterFactory() {super(CustomConfig.class);}@Overridepublic List<String> shortcutFieldOrder() {return Arrays.asList("switchStatus");}@Overridepublic GatewayFilter apply(CostGatewayFilterFactory.CustomConfig config) {return new GatewayFilter() {@Overridepublic Mono<Void> filter(ServerWebExchange exchange,GatewayFilterChain chain) {if (!config.switchStatus.equalsIgnoreCase("on")) {// 如果这个开关是关闭状态return chain.filter(exchange);}long sTime = System.currentTimeMillis();exchange.getAttributes().put("STIME", sTime);return chain.filter(exchange).then(Mono.fromRunnable(() -> {long stime = (long) exchange.getAttributes().get("STIME");long cost = System.currentTimeMillis() - stime;System.out.println("cost is : " + cost + " ms");}));}@Overridepublic String toString() {return filterToStringCreator(CostGatewayFilterFactory.this).append(config.getSwitchStatus(), config.getSwitchStatus()).toString();}};}public static class CustomConfig {private String switchStatus;public String getSwitchStatus() {return switchStatus;}public void setSwitchStatus(String switchStatus) {this.switchStatus = switchStatus;}}
}
配置
routes:- id: gateway-provideruri: http://127.0.0.1:8088predicates:- Path=/provider/**filters:- StripPrefix=1- Cost=ON # 这个名字取前面GatewayFilterFactory的
自定义全局
@Component
public class GlobalCustomFilter implements GlobalFilter {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 过滤前System.out.println("Before : " + exchange.getRequest().getURI());return chain.filter(exchange).then(Mono.fromRunnable(() -> {long stime = (long) exchange.getAttributes().get("STIME");long cost = System.currentTimeMillis() - stime;System.out.println("End cost time is : " + cost);}));}
}
Spring Cloud Gateway 是基于Netty 实现的,而不是Tomcat。我本来想试试mvc的过滤器和gateway的过滤器的优先级,结果怎么配置filter也不生效,原来如此,菜狗终究是菜狗。
可以换为Tomcat
转发重定向原理
- Gateway 框架体系处理的入口org.springframework.http.server.reactive.ReactorHttpHandlerAdapter
- 构建网关上下文:org.springframework.web.server.adapter.HttpWebHandlerAdapter
- 遍历 Mapping 获取真实处理请求的 Handler org.springframework.web.reactive.DispatcherHandler
- 构建过滤器链:org.springframework.cloud.gateway.handler.FilteringWebHandler
- 过滤器必经之路:org.springframework.cloud.gateway.handler.FilteringWebHandler.DefaultGatewayFilterChain
- 负载均衡过滤器:org.springframework.cloud.gateway.filter.LoadBalancerClientFilter
- 利用 Netty 发送网络请求过滤器:org.springframework.cloud.gateway.filter.NettyRoutingFilter

RouteToRequestUrlFilter 这个过滤器处理了Route的配置,并且将请求的真实地址存放到了
URI mergedUrl = UriComponentsBuilder.fromUri(uri)// .uri(routeUri).scheme(routeUri.getScheme()).host(routeUri.getHost()).port(routeUri.getPort()).build(encoded).toUri();
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, mergedUrl);
NettyRoutingFilter 进行了真正的转发调用

这个经典的图必须贴上:

相关文章:
微服务-Gateway
案例搭建 官网地址 父Pom <com.alibaba.cloud.version>2.2.8.RELEASE</com.alibaba.cloud.version> <com.cloud.version>Hoxton.SR12</com.cloud.version> <com.dubbo.version>2.2.7.RELEASE</com.dubbo.version> <dependencyManagem…...
【用队列实现栈】【用栈实现队列】Leetcode 232 225
【用队列实现栈】【用栈实现队列】Leetcode 232 225 队列的相关操作栈的相关操作用队列实现栈用栈实现队列 ---------------🎈🎈题目链接 用队列实现栈🎈🎈------------------- ---------------🎈🎈题目链…...
Angular系列教程之观察者模式和RxJS
文章目录 引言RxJS简介RxJS中的设计模式观察者模式迭代器模式 示例代码RxJS 在 Angular 中的应用总结 引言 在Angular开发中,我们经常需要处理异步操作,例如从后端获取数据或与用户的交互。为了更好地管理这些异步操作,Angular中引入了RxJS&…...
展厅设计中搭建的小常识
1、展厅的安全问题 展厅的空间面积大,平时为出现公开展览时人员较少,但遇到开展活动、会展展览时人流量将大大增多,无论是临时的展厅展示还是长期的展示安全问题即使不说都应该是装饰的重中之重,所以在从前期设计规划到后期施工采…...
LeetCode 98. 验证二叉搜索树
98. 验证二叉搜索树 给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下: 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 示例…...
自定义shell工具函数之pull_image()
这是一个名为pull_image的Shell脚本函数。让我来解释一下这个函数的功能: function pull_image() {image$1DOCKER_IMAGE_MIRROR$(get_config_or_env DOCKER_IMAGE_MIRROR)if [[ "${DOCKER_IMAGE_MIRROR}" "1" ]]; thenif [[ "$(uname -m…...
2019年认证杯SPSSPRO杯数学建模C题(第二阶段)保险业的数字化变革全过程文档及程序
2019年认证杯SPSSPRO杯数学建模 基于统计建模的车险业数字变革研究 C题 保险业的数字化变革 原题再现: 车险,即机动车辆保险。保险自身是一种分散风险、消化损失的经济补偿制度,车险即为分散机动车辆在行驶过程中可能发作的未知风险和损失…...
【数据结构和算法】反转链表
其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、题目描述 二、题解 2.1 方法一:迭代(双指针) 2.2 方法二:递归 三、代码 3.…...
What is `GenericFilterBean` does?
GenericFilterBean 是 SpringWeb 框架中提供的一个抽象基类,其对 javax.servlet.Filter接口进行了封装和扩展,它简化了在 Servlet环境下创建自定义过滤器的工作。 GenericFilterBean 主要特点包括: 集成 Spring 容器: 由于它是一…...
突破通胀风险,聚焦现货黄金投资机遇
随着全球经济不断发展和金融市场的波动,通胀风险成为各界关注的焦点。在面对通胀带来的财务压力和资产贬值的威胁时,投资者都在寻找稳定且可靠的避险资产。而现货黄金作为一种值得瞩目的投资工具,正吸引着越来越多投资者的目光。 黄金作为一种…...
Jenkins集成Sonar Qube
下载插件 重启Jenkins 容器 sonarqube 使用令牌 Jenkins 配置 重新构建...
Angular系列教程之zone.js和NgZone
文章目录 什么是zone.jsZone的工作原理Zone的常见用途NgZone:Angular中的zone.js使用NgZone使用NgZone执行代码使用NgZone外部检测 结论 什么是zone.js 在Angular中,zone.js是一个非常重要的库,它为我们提供了一种跟踪和管理异步操作的机制。…...
阿里巴巴的第二代通义千问可能即将发布:Qwen2相关信息已经提交HuggingFace官方的transformers库
本文来自DataLearnerAI官方网站:阿里巴巴的第二代通义千问可能即将发布:Qwen2相关信息已经提交HuggingFace官方的transformers库 | 数据学习者官方网站(Datalearner) 通义千问是阿里巴巴开源的一系列大语言模型。Qwen系列大模型最高参数量720亿…...
肯尼斯·里科《C和指针》第6章 指针(6)编程的练习:查找字符
1.编写一个函数,它在一个字符串中进行搜索,查找在一个给定字符集合中出现的所有字符。这个函数的原型如下: char *find_char( char const *source, char const *chars ); 它的基本想法是查找source字符串中匹配chars字符串中任何字符的第1个…...
Entity Framework知识点整理
Entity Framework Entity Framework(EF)是微软提供的一种对象关系映射(Object-Relational Mapping,ORM)框架,用于在.NET应用程序和关系型数据库之间建立映射关系。它简化了数据访问层的开发,使…...
源码搭建教学:连锁餐饮APP开发实战
连锁餐饮APP,对于很多从事餐饮行业的人来说不会陌生,同样这个项目本身就有着很高的热度。今天,小编将深入为大家讲述一下此系统的前后端开发、数据库设计、用户界面设计等方面,让您深入了解全栈开发的方方面面。 一、项目准备与规…...
使用JavaScript实现一个在线画板
一、引言 随着Web技术的发展,网页上的交互性变得越来越重要。一个在线画板是一个很好的例子,它允许用户在网页上自由创作。在这篇博客中,我们将使用HTML5的Canvas元素和JavaScript来实现一个简单的在线画板 二、HTML结构 首先,…...
微信小程序如何自定义导航栏,怎么确定导航栏及状态栏的高度?导航栏被刘海、信号图标给覆盖了怎么办?
声明:本文为了演示效果,颜色采用的比较显眼,可根据实际情况修改颜色 问题描述 当我们在JSON中将navigationStyle设置成custom后,当前页面的顶部导航栏就需要我们制作了,但出现了一下几个问题: 导航栏的高…...
Spring Boot “How-to“ 指南中文文档-上
本文为官方文档直译版本。原文链接 篇幅较长,遂分两篇 Spring Boot "How-to" 指南中文文档-上 引言Spring Boot Application创建自己的FailureAnalyzer(故障分析器)自动配置故障诊断启动前自定义环境或应用程序上下文构建 Applicat…...
快速了解spring boot中的@idempotent注解
目的:一定时间内,同样的请求(业务参数相同)访问同一个接口,则只能成功一次,其余被拒绝 幂等实现原理就是利用AOP面向切面编程,在执行业务逻辑之前插入一个方法,生成一个token,存入redis并插入到…...
【Visual Leak Detector】跨平台 QT 项目集成 VLD 的便携式部署方案
1. Visual Leak Detector 与 QT 开发的那些事儿 做 C 开发的朋友应该都遇到过内存泄漏这个头疼的问题。特别是用 QT 开发跨平台应用时,随着项目规模扩大,内存管理就变得格外棘手。Visual Leak Detector(简称 VLD)这个轻量级工具简…...
如何用FanControl彻底告别电脑噪音?Windows风扇控制终极解决方案
如何用FanControl彻底告别电脑噪音?Windows风扇控制终极解决方案 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_T…...
TPAMI 2026 | 雨雾噪模糊全搞定!CPL 框架让图像复原告别单一任务限制
点击上方“小白学视觉”,选择加"星标"或“置顶” 重磅干货,第一时间送达在日常拍摄中,一张照片可能同时遭遇噪声、雾霾、雨滴等多种退化问题,而传统图像复原方法要么只能处理单一退化类型,要么在多任务场景下…...
Wangle客户端开发实战:从零开始构建高效网络应用
Wangle客户端开发实战:从零开始构建高效网络应用 【免费下载链接】wangle Wangle is a framework providing a set of common client/server abstractions for building services in a consistent, modular, and composable way. 项目地址: https://gitcode.com/g…...
成电计算机复试面试:如何用一份‘心机’简历引导老师提问,并提前准备好答案?
计算机复试策略:如何用结构化简历设计引导面试走向 站在电子科技大学计算机复试的考场外,大多数考生都在反复背诵技术概念和项目细节,却很少有人意识到——面试本质上是一场精心设计的对话博弈。那些最终获得高分的考生,往往不是知…...
舰艇推进电机供电流程优化方案
舰艇推进电机供电流程优化方案 第一章 绪论 1.1 背景与意义 现代舰艇(如驱逐舰、潜艇、全电推进船舶)广泛采用综合电力系统。传统的供电流程中,推进电机作为最大的非线性负载,其负载突变(如急加速、倒车、波浪冲击导致的螺旋桨甩尾)会通过直流母线回馈至发电机组,导致…...
BUUCTF-[HITCON 2017]SSRFme
代码分析<?phpif (isset($_SERVER[HTTP_X_FORWARDED_FOR])) { //HTTP_X_FORWARDED_FOR可以获取客户端真正ip地址,和各个代理IP地址$http_x_headers explode(,, $_SERVER[HTTP_X_FORWARDED_FOR]); //拆分字符串,以,分割$_SERVER[REMOTE…...
迈瑞医疗营收超330亿,国际业务持续发力未来何在?
最近的财报季,各家上市公司的财报都牵动着每个人的心,就在最近迈瑞医疗的成绩单公布,营收超330亿,国际业务持续向好,这样的成绩单我们到底该怎么看待呢?一、迈瑞医疗业绩稳健向好据每日经济新闻的报道&…...
Obsidian图像转换:提升笔记效率的格式优化解决方案
Obsidian图像转换:提升笔记效率的格式优化解决方案 【免费下载链接】obsidian-image-converter ⚡️ Convert, compress, resize, annotate, markup, draw, crop, rotate, flip, align images directly in Obsidian. Drag-resize, rename with variables, batch pro…...
千问3.5-2B博物馆导览:展品图理解、说明牌OCR与个性化讲解生成
千问3.5-2B博物馆导览:展品图理解、说明牌OCR与个性化讲解生成 1. 博物馆导览新体验 想象一下,当你站在博物馆的展品前,只需用手机拍下展品照片,就能立即获得专业的讲解内容、展品背景故事,甚至还能根据你的兴趣偏好…...
