当前位置: 首页 > news >正文

微服务-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 队列的相关操作栈的相关操作用队列实现栈用栈实现队列 ---------------&#x1f388;&#x1f388;题目链接 用队列实现栈&#x1f388;&#x1f388;------------------- ---------------&#x1f388;&#x1f388;题目链…...

Angular系列教程之观察者模式和RxJS

文章目录 引言RxJS简介RxJS中的设计模式观察者模式迭代器模式 示例代码RxJS 在 Angular 中的应用总结 引言 在Angular开发中&#xff0c;我们经常需要处理异步操作&#xff0c;例如从后端获取数据或与用户的交互。为了更好地管理这些异步操作&#xff0c;Angular中引入了RxJS&…...

展厅设计中搭建的小常识

1、展厅的安全问题 展厅的空间面积大&#xff0c;平时为出现公开展览时人员较少&#xff0c;但遇到开展活动、会展展览时人流量将大大增多&#xff0c;无论是临时的展厅展示还是长期的展示安全问题即使不说都应该是装饰的重中之重&#xff0c;所以在从前期设计规划到后期施工采…...

LeetCode 98. 验证二叉搜索树

98. 验证二叉搜索树 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 示例…...

自定义shell工具函数之pull_image()

这是一个名为pull_image的Shell脚本函数。让我来解释一下这个函数的功能&#xff1a; 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题 保险业的数字化变革 原题再现&#xff1a; 车险&#xff0c;即机动车辆保险。保险自身是一种分散风险、消化损失的经济补偿制度&#xff0c;车险即为分散机动车辆在行驶过程中可能发作的未知风险和损失…...

【数据结构和算法】反转链表

其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、题目描述 二、题解 2.1 方法一&#xff1a;迭代&#xff08;双指针&#xff09; 2.2 方法二&#xff1a;递归 三、代码 3.…...

What is `GenericFilterBean` does?

GenericFilterBean 是 SpringWeb 框架中提供的一个抽象基类&#xff0c;其对 javax.servlet.Filter接口进行了封装和扩展&#xff0c;它简化了在 Servlet环境下创建自定义过滤器的工作。 GenericFilterBean 主要特点包括&#xff1a; 集成 Spring 容器&#xff1a; 由于它是一…...

突破通胀风险,聚焦现货黄金投资机遇

随着全球经济不断发展和金融市场的波动&#xff0c;通胀风险成为各界关注的焦点。在面对通胀带来的财务压力和资产贬值的威胁时&#xff0c;投资者都在寻找稳定且可靠的避险资产。而现货黄金作为一种值得瞩目的投资工具&#xff0c;正吸引着越来越多投资者的目光。 黄金作为一种…...

Jenkins集成Sonar Qube

下载插件 重启Jenkins 容器 sonarqube 使用令牌 Jenkins 配置 重新构建...

Angular系列教程之zone.js和NgZone

文章目录 什么是zone.jsZone的工作原理Zone的常见用途NgZone&#xff1a;Angular中的zone.js使用NgZone使用NgZone执行代码使用NgZone外部检测 结论 什么是zone.js 在Angular中&#xff0c;zone.js是一个非常重要的库&#xff0c;它为我们提供了一种跟踪和管理异步操作的机制。…...

阿里巴巴的第二代通义千问可能即将发布:Qwen2相关信息已经提交HuggingFace官方的transformers库

本文来自DataLearnerAI官方网站&#xff1a;阿里巴巴的第二代通义千问可能即将发布&#xff1a;Qwen2相关信息已经提交HuggingFace官方的transformers库 | 数据学习者官方网站(Datalearner) 通义千问是阿里巴巴开源的一系列大语言模型。Qwen系列大模型最高参数量720亿&#xf…...

肯尼斯·里科《C和指针》第6章 指针(6)编程的练习:查找字符

1.编写一个函数&#xff0c;它在一个字符串中进行搜索&#xff0c;查找在一个给定字符集合中出现的所有字符。这个函数的原型如下&#xff1a; char *find_char( char const *source, char const *chars ); 它的基本想法是查找source字符串中匹配chars字符串中任何字符的第1个…...

Entity Framework知识点整理

Entity Framework Entity Framework&#xff08;EF&#xff09;是微软提供的一种对象关系映射&#xff08;Object-Relational Mapping&#xff0c;ORM&#xff09;框架&#xff0c;用于在.NET应用程序和关系型数据库之间建立映射关系。它简化了数据访问层的开发&#xff0c;使…...

源码搭建教学:连锁餐饮APP开发实战

连锁餐饮APP&#xff0c;对于很多从事餐饮行业的人来说不会陌生&#xff0c;同样这个项目本身就有着很高的热度。今天&#xff0c;小编将深入为大家讲述一下此系统的前后端开发、数据库设计、用户界面设计等方面&#xff0c;让您深入了解全栈开发的方方面面。 一、项目准备与规…...

使用JavaScript实现一个在线画板

一、引言 随着Web技术的发展&#xff0c;网页上的交互性变得越来越重要。一个在线画板是一个很好的例子&#xff0c;它允许用户在网页上自由创作。在这篇博客中&#xff0c;我们将使用HTML5的Canvas元素和JavaScript来实现一个简单的在线画板 二、HTML结构 首先&#xff0c;…...

微信小程序如何自定义导航栏,怎么确定导航栏及状态栏的高度?导航栏被刘海、信号图标给覆盖了怎么办?

声明&#xff1a;本文为了演示效果&#xff0c;颜色采用的比较显眼&#xff0c;可根据实际情况修改颜色 问题描述 当我们在JSON中将navigationStyle设置成custom后&#xff0c;当前页面的顶部导航栏就需要我们制作了&#xff0c;但出现了一下几个问题&#xff1a; 导航栏的高…...

Spring Boot “How-to“ 指南中文文档-上

本文为官方文档直译版本。原文链接 篇幅较长&#xff0c;遂分两篇 Spring Boot "How-to" 指南中文文档-上 引言Spring Boot Application创建自己的FailureAnalyzer&#xff08;故障分析器&#xff09;自动配置故障诊断启动前自定义环境或应用程序上下文构建 Applicat…...

快速了解spring boot中的@idempotent注解

目的&#xff1a;一定时间内&#xff0c;同样的请求(业务参数相同)访问同一个接口&#xff0c;则只能成功一次&#xff0c;其余被拒绝 幂等实现原理就是利用AOP面向切面编程&#xff0c;在执行业务逻辑之前插入一个方法&#xff0c;生成一个token&#xff0c;存入redis并插入到…...

RestClient

什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端&#xff0c;它允许HTTP与Elasticsearch 集群通信&#xff0c;而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级&#xff…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...

MySQL:分区的基本使用

目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区&#xff08;Partitioning&#xff09;是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分&#xff08;分区&#xff09;可以独立存储、管理和优化&#xff0c;…...