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

统一网关 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. 前言 通过前面的学习我们知道&#xff0c;通过 Feign 就可以向指定的微服务发起 http 请求&#xff0c;完成远程调用。但是这里有一个问题&am…...

【征服redis1】基础数据类型详解和应用案例

博客计划 &#xff0c;我们从redis开始&#xff0c;主要是因为这一块内容的重要性不亚于数据库&#xff0c;但是很多人往往对redis的问题感到陌生&#xff0c;所以我们先来研究一下。 本篇&#xff0c;我们先看一下redis的基础数据类型详解和应用案例。 1.redis概述 以mysql为…...

【WPF.NET开发】WPF中的XAML资源

本文内容 使用 XAML 中的资源静态和动态资源静态资源动态资源样式、DataTemplate 和隐式键 资源是可以在应用中的不同位置重复使用的对象。 资源的示例包括画笔和样式。 本概述介绍如何使用 Extensible Application Markup Language (XAML) 中的资源。 你还可以使用代码创建和…...

ChatGPT 淘金潮(全)

原文&#xff1a;The ChatGPT GoldRush 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 一、ChatGPT 简介 什么是 ChatGPT&#xff1f; ChatGPT 是由 OpenAI 基于 GPT-4 架构创建的大型语言模型。它旨在理解和回应自然语言文本输入&#xff0c;使得可以与机器进行对话…...

【零基础入门Python数据分析】Anaconda3 JupyterNotebookseaborn版

目录 一、安装环境 python介绍 anaconda介绍 jupyter notebook介绍 anaconda3 环境安装 解决JuPyter500&#xff1a;Internal Server Error问题-CSDN博客 Jupyter notebook快捷键操作大全 二、Python基础入门 数据类型与变量 数据类型 变量及赋值 布尔类型与逻辑运算…...

C++面试:单例模式、工厂模式等简单的设计模式 创建型、结构型、行为型设计模式的应用技巧

理解和能够实现基本的设计模式是非常重要的。这里&#xff0c;我们将探讨两种常见的设计模式&#xff1a;单例模式和工厂模式&#xff0c;并提供一些面试准备的建议。 目录 单例模式 (Singleton Pattern) 工厂模式 (Factory Pattern) 面试准备 1. 理解设计模式的基本概念…...

Oracle JDK 8 中的 computeIfAbsent 方法及实践

Java 8 引入了一系列新特性&#xff0c;其中之一是对 Map 接口的增强&#xff0c;其中包括了 computeIfAbsent 方法。这个方法为处理映射提供了一种便捷而强大的方式&#xff0c;允许在键不存在或对应的值为 null 时&#xff0c;动态计算新的值并将其放入映射。在本篇博客中&am…...

华为设备vlan下配置MSTP,STP选举

核心代码,不同实例&#xff0c;承载不同流量&#xff0c;为每个实例设置一个根网桥达到分流的效果 stp region-config //进入stp区域的设置 region-name R1 //区域命名为R1 instance 1 vlan 10 …...

案例学Python:filter()函数的用法,高级!

大家好&#xff0c;这里是程序员晚枫&#xff0c;又来分享有用的Python知识了。 Python之所以好用&#xff0c;是因为有大量用于科学计算的内置函数和第三方库。用好这些第三方库&#xff0c;可以显著提高我们编程的速度和质量。 今天我们一起来看一下Python中一个重要的内置…...

jmeter--7.BeanShell

目录 1. beanshell常用语法 1.1 log&#xff1a;日志写入 1.2 vars&#xff1a;设置和引用局部变量&#xff08;同线程组&#xff09; 1.3 props&#xff1a;设置和引用全局变量&#xff08;跨线程组&#xff09; 1.4 prev&#xff1a;获取前一个请求返回的信息 2. beans…...

第 3 场 蓝桥杯小白入门赛 解题报告 | 珂学家 | 单调队列优化的DP + 三指针滑窗

前言 整体评价 T5, T6有点意思&#xff0c;这场小白入门场&#xff0c;好像没真正意义上的签到&#xff0c;整体感觉是这样。 A. 召唤神坤 思路: 前后缀拆解 #include <iostream> #include <algorithm> #include <vector> using namespace std;int main()…...

debian apt 装 mysql8

MySQL &#xff1a;&#xff1a; MySQL 8.0 参考手册 &#xff1a;&#xff1a; 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

终于考完试了&#xff0c;寒假期间将会每天持续更新&#xff01; 447. 回旋镖的数量(Day 37) 给定平面上 n 对 互不相同 的点 points &#xff0c;其中 points[i] [xi, yi] 。回旋镖 是由点 (i, j, k) 表示的元组 &#xff0c;其中 i 和 j 之间的欧式距离和 i 和 k 之间的欧…...

产品百度百科怎么创建?产品如何上百度百科?

百度百科作为一个权威的信息平台&#xff0c;承载着巨大的流量和曝光度。对于一个产品来说&#xff0c;能够在百度百科上拥有一席之地&#xff0c;无疑是一种极高的荣誉&#xff0c;同时也是提升品牌知名度、增加信任度的重要手段。产品百度百科不仅能够详细、全面地介绍产品信…...

Vue keep-alive的使用和原理解析

✨ 专栏介绍 在当今Web开发领域中&#xff0c;构建交互性强、可复用且易于维护的用户界面是至关重要的。而Vue.js作为一款现代化且流行的JavaScript框架&#xff0c;正是为了满足这些需求而诞生。它采用了MVVM架构模式&#xff0c;并通过数据驱动和组件化的方式&#xff0c;使…...

Fine-tuning:个性化AI的妙术

在本篇文章中,我们将深入探讨Fine-tuning的概念、原理以及如何在实际项目中运用它,以此为初学者提供一份入门级的指南。 一、什么是大模型 ChatGPT大模型今年可谓是大火,在正式介绍大模型微调技术之前,为了方便大家理解,我们先对大模型做一个直观的抽象。 本质上,现在…...

说清楚Kubernetes、Docker、Dockershim、Containerd、runC、CRI、OCI的关系

Kubernetes v1.20版本 的 release note 里说 deprecated docker。并且在后续版本 v1.24 正式删除了 dockershim 组件&#xff0c;这对我们有什么影响呢&#xff1f;Kubernetes 1.20: The Raddest Release | Kubernetes 为了搞明白这件事情&#xff0c;以及理解一系列容器名词 …...

x-cmd pkg | trash-cli - 类 Unix 系统的命令行垃圾桶

目录 简介首次用户技术特点竞品和相关作品进一步阅读 简介 trash-cli 是类 Unix 系统的命令行垃圾桶&#xff0c;用于移动文件到回收站&#xff0c;同时会记录文件的原地址和删除日期。 该工具使用与 GNOME、KDE ​​和 XFCE 等桌面环境相同的垃圾桶&#xff0c;所以即使是非 …...

基于Java+SpringBoot+vue实现图书借阅和销售商城一体化系统

基于JavaSpringBootvue实现图书借阅和销售商城一体化系统 &#x1f345; 作者主页 央顺技术团队 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; &#x1f345; 查看下方微信号获取联系方式 承接各种定制系…...

集成xxljob项目如何迁移到K8S

前言 大家好&#xff0c;今天我们将基于XXL-Job&#xff0c;探讨任务调度迁移到云端的相关话题。 XXL-Job是一款功能强大、易用可靠的国产分布式任务调度平台&#xff0c;是目前国内使用比较广泛的分布式任务调度平台之一。它的主要特点包括&#xff1a; 支持分布式、多线程…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录

ASP.NET Core 是一个跨平台的开源框架&#xff0c;用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录&#xff0c;以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

分布式增量爬虫实现方案

之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面&#xff0c;避免重复抓取&#xff0c;以节省资源和时间。 在分布式环境下&#xff0c;增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路&#xff1a;将增量判…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...