07-微服务getaway网关详解

news2025/2/25 13:28:31

一、初识网关

在微服务架构中,一个系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢?如果没有网关的存在,我们只能在客户端记录每个微服务的地址,然后分别去调用。这样的话会产生很多问题,例如:

  • 客户端多次请求不同的微服务,增加客户端代码或配置编写的复杂性
  • 认证复杂,每个微服务都有独立认证
  • 存在跨域请求,在一定场景下处理相对复杂
    为解决上面的问题所以引入了网关的概念:所谓的API网关,就是指系统的统一入口,提供内部服务的路由中转,为客户端提供统一服务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权、监控、路由转发等

1.1 网关的分类

  • Zuul 1.x
    Netflix开源的网关,基于Servlet框架构建,功能丰富,使用JAVA开发,易于二次开发 问题:即一个线程处理一次连接请求,这种方式在内部延迟严重、设备故障较多情况下会引起存活的连接增多和线程增加的情况发生。
  • Zuul 2.x
    Zuul2 采用了Netty实现异步非阻塞编程模型,每个 CPU 核一个线程,处理所有的请求和响应,请求和响应的生命周期是通过事件和回调来处理的,这种方式减少了线程数量,因此开销较小。
  • GateWay
    Spring公司为了替换Zuul而开发的网关服务,底层为Netty,将在下面具体介绍。
  • Nginx+lua
    使用nginx的反向代理和负载均衡可实现对api服务器的负载均衡及高可用,lua是一种脚本语言,可以来编写一些简单的逻辑, nginx支持lua脚本,问题在于:无法融入到微服务架构中
  • Kong
    基于Nginx+Lua开发,性能高,稳定,有多个可用的插件(限流、鉴权等等)可以开箱即用。 问题:只支持Http协议;二次开发,自由扩展困难;提供管理API,缺乏更易用的管控、配置方式。

1.2 gateway

Spring Cloud Gateway 基于Spring Boot 2.x、Spring WebFlux和Project Reactor,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。它的目标是替代Netflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控和限流。基于Webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架
特点:

  1. 性能强劲:是Zuul的1.6倍
  2. 功能强大:内置了很多实用的功能,例如转发、监控、限流等
  3. 设计优雅,容易扩展

1.2.1 基本理解

路由(Route) 是 gateway 中最基本的组件之一,表示一个具体的路由信息载体。主要定义了下面的几个信息:

  • id:路由标识、区别于其他route
  • uri:路由指向的目的地uri,即客户端请求最终被转发到的微服务
  • order:用于多个route之间的排序,数值越小排序越靠前,匹配优先级越高
  • predicate:断言的作用是进行条件判断,只有断言都返回真,才会真正的执行路由
  • filter:过滤器用于修改请求和响应信息

1.2.2 执行流程

  1. Gateway Client向Gateway Server发送请求
  2. 请求首先会被HttpWebHandlerAdapter进行提取组装成网关上下文
  3. 然后网关的上下文会传递到DispatcherHandler,它负责将请求分发给RoutePredicateHandlerMapping
  4. RoutePredicateHandlerMapping负责路由查找,并根据路由断言判断路由是否可用
  5. 如果断言成功,由FilteringWebHandler创建过滤器链并调用
  6. 请求会一次经过PreFilter–微服务–PostFilter的方法,最终返回响应

1.2.3 核心流程解读

image.png

客户端向 Spring Cloud Gateway 发出请求。如果Gateway Handler Mapping确定请求与路由匹配,则将其发送到Gateway Web Handler 处理程序。此处理程序通过特定于请求的Fliter链运行请求。Fliter被虚线分隔的原因是Fliter可以在发送代理请求之前(pre)和之后(post)运行逻辑。执行所有pre过滤器逻辑。然后进行代理请求。发出代理请求后,将运行“post”过滤器逻辑。

过滤器作用:

  • Filter在pre类型的过滤器可以做参数效验、权限效验、流量监控、日志输出、协议转换等。
  • Filter在post类型的过滤器可以做响应内容、响应头的修改、日志输出、流量监控等
  • 这两种类型的过滤器有着非常重要的作用

核心点

  • Route(路由)
    路由是构建网关的基础模块,它由ID,目标URI,包括一些列的断言和过滤器组成,如果断言为true则匹配该路由
  • Predicate(断言)
    参考的是Java8的java.util.function.Predicate,开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),请求与断言匹配则进行路由
  • Filter(过滤)
    指的是Spring框架中GateWayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。
  • 三个核心点连起来:
    当用户发出请求到达GateWay,GateWay会通过一些匹配条件,定位到真正的服务节点,并在这个转发过程前后,进行一些及细化控制。其中Predicate就是我们匹配的条件,而Filter可以理解为一个拦截器,有了这两个点,再加上目标URI,就可以实现一个具体的路由了。

GateWay核心的流程就是:路由转发+执行过滤器链

二、 网关搭建

2.1 创建一个子模块。端口为9999

image.png

版本对应地址:https://spring.io/projects/spring-cloud

2.2 引入依赖

因为gateway是Spring cloud的,我们需要在父工程引入spring cloud的依赖

<!--spring cloud Hoxton.SR12-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>${spring-cloud-gateway-varsion}</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

在我们的9999网关服务引入nacos和geteway依赖

<dependency>  
    <groupId>com.alibaba.cloud</groupId>  
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>  
</dependency>  
<dependency>  
    <groupId>org.springframework.cloud</groupId>  
    <artifactId>spring-cloud-starter-gateway</artifactId>  
</dependency>

配置yaml文件

server:  
  port: 9999  
spring:  
  application:  
    name: cloud-getway-service  
  cloud:  
    nacos:  
      discovery:  
        server-addr: localhost:8848  
    gateway:  
      discovery:  
        locator:  
          enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由  
      routes:  
        - id: nacos-payment-provider  
          uri: http://localhost:9001/nacos-payment-provider  
          predicates:  
            - Path=/test/**

启动Nacos服务,9999网关服务,9001服务,通过浏览器访问其他服务,效果如下:
image.png

2.3 网关配置路由的第二种方式

我们可以通过代码来配置网关
新建配置类,交由Spring管理

@Configuration  
public class TestGetWayConfig {  
  
    @Bean  
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {  
        return builder.routes()  
                .route("nacos-payment-provider", r -> r.path("/test/**").uri("http://localhost:9001/nacos-payment-provider"))  
                .route("nacos-payment-provider2", r -> r.path("/**").uri("http://localhost:9002/nacos-payment-provider2"))  
                .build();  
    }  
}

正常访问浏览器即可。

三、配置动态路由

  1. gateway.discovery.locator.enabled: true 开启自动路由功能
  2. routes中的uri其实最后是不需要服务名称的,这个位置其实只需要指定的localhost:9001即可
    自动路由规则
  3. discovery.locator.enabled: true 这个配置默认为false,但是如果为true,就是开启了通过serviceId转发到具体的服务实例。localhost:9999/ServiceID/test/
  4. geteway开启了自动路由后自带负载均衡功能

手动配置负载均衡
uri: lb

server:
  port: 9999
spring:
  application:
    name: cloud-gateway-9999
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    gateway:
      discovery:
        locator:
          enabled: true #开启自动路由功能(此时可以关闭)
      routes: # 路由
        - id: nacos-payment-provider #路由ID,没有固定要求,但是要保证唯一,建议配合服务名
          uri: lb://nacos-payment-provider # 匹配提供服务的路由地址
          predicates: # 断言
            - Path=/test/** 

四、断言Predicate

4.1 断言种类

  1. After:匹配在指定日期时间之后发生的请求。
  2. Before:匹配在指定日期之前发生的请求。
  3. Between:需要指定两个日期参数,设定一个时间区间,匹配此时间区间内的请求。
  4. Cookie:需要指定两个参数,分别为name和regexp(正则表达式),也可以理解Key和Value,匹配具有给定名称且其值与正则表达式匹配的Cookie。
  5. Header:需要两个参数header和regexp(正则表达式),也可以理解为Key和Value,匹配请求携带信息。
  6. Host:匹配当前请求是否来自于设置的主机。
  7. Method:可以设置一个或多个参数,匹配HTTP请求,比如GET、POST
  8. Path:匹配指定路径下的请求,可以是多个用逗号分隔
  9. Query:需要指定一个或者多个参数,一个必须参数和一个可选的正则表达式,匹配请求中是否包含第一个参数,如果有两个参数,则匹配请求中第一个参数的值是否符合正则表达式。
  10. RemoteAddr:匹配指定IP或IP段,符合条件转发。
  11. Weight:需要两个参数group和weight(int),实现了路由权重功能,按照路由权重选择同一个分组中的路由

参考Spring官网案例:

https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories

五、Filter 过滤器

5.1 内置Filter

  1. GateWay内置的Filter生命周期为两种:pre(业务逻辑之前)、post(业务逻辑之后)
  2. GateWay本身自带的Filter分为两种: GateWayFilter(单一)、GlobalFilter(全局)
  3. 单一的有32种,全局的有9
  4. 官方网址:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#global-filters

5.2 自定义Filter

工作中最常用的就是自定义顾虑器

我们需要创建一个自定义过滤器类,实现Ordered, GlobalFilter


@Component
@Slf4j
public class MyFilter implements Ordered, GlobalFilter {
    /**
     * @param exchange 可以拿到对应的request和response
     * @param chain 过滤器链
     * @return 是否放行
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String username = exchange.getRequest().getQueryParams().getFirst("username");
        log.info("*************MyFilter:"+new Date());
        if(username == null){
            log.info("**********用户名为null,非法用户,请求被拒绝!");
            //如果username为空,返回状态码为406,不可接受的请求
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    /**
     * 加载过滤器的顺序
     * @return 整数数字越小优先级越高
     */
    @Override
    public int getOrder() {
        return 0;
    }
}

访问浏览器,如果我们的接口地址中没有携带username参数则拒绝访问,否则成功响应

如果对你有帮助,可以关注博主(不定期更新各种技术文档)
给博主一个免费的点赞以示鼓励,谢谢 ! 欢迎各位🔎点赞👍评论收藏⭐️

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1391323.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设计模式之依赖倒转原则

在软件开发的世界里&#xff0c;设计模式一直是提升代码质量、确保软件稳定性以及优化软件可维护性的重要工具。而在这其中&#xff0c;依赖倒转原则无疑是其中最具代表性的设计模式之一。那么&#xff0c;什么是依赖倒转原则&#xff1f;它又为何如此重要&#xff1f;让我们一…

鼎捷软件获评国家级智能制造“AAA级集成实施+AA级咨询设计”供应商

为贯彻落实《“十四五”智能制造发展规划》&#xff0c;健全智能制造系统解决方案供应商(以下简称“供应商”)分类分级体系&#xff0c;推动供应商规范有序发展&#xff0c;智能制造系统解决方案供应商联盟组织开展了供应商分类分级评定(第一批)工作&#xff0c;旨在遴选一批专…

Python--GIL(全局解释器锁)

在Python中&#xff0c;GIL&#xff08;全局解释器锁&#xff09;是一个非常重要的概念&#xff0c;它对Python的多线程编程有着深远的影响。GIL是Python解释器级别的锁&#xff0c;用于保证任何时刻只有一个线程在执行Python字节码。这意味着即使在多核处理器上&#xff0c;Py…

[HTML]Web前端开发技术13(HTML5、CSS3、JavaScript )横向二级导航菜单 Web页面设计实例——喵喵画网页

希望你开心&#xff0c;希望你健康&#xff0c;希望你幸福&#xff0c;希望你点赞&#xff01; 最后的最后&#xff0c;关注喵&#xff0c;关注喵&#xff0c;关注喵&#xff0c;佬佬会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我真的…

离线数据仓库-关于增量和全量

数据同步策略 数据仓库同步策略概述一、数据的全量同步二、数据的增量同步三、数据同步策略的选择 数据仓库同步策略概述 应用系统所产生的业务数据是数据仓库的重要数据来源&#xff0c;我们需要每日定时从业务数据库中抽取数据&#xff0c;传输到数据仓库中&#xff0c;之后…

探索Redis特殊数据结构:Bitmaps(位图)在实际中的应用

一、概述 Redis官方提供了多种数据类型&#xff0c;除了常见的String、Hash、List、Set、zSet之外&#xff0c;还包括Stream、Geospatial、Bitmaps、Bitfields、Probabilistic&#xff08;HyperLogLog、Bloom filter、Cuckoo filter、t-digest、Top-K、Count-min sketch、Confi…

一文掌握SpringBoot注解之@Async知识文集(1)

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

手把手教你搭建一个数据可视化看板

前言 俗话说的好&#xff0c;“字不如表&#xff0c;表不如图”、“有图有真相&#xff0c;一图胜千言”。 数据可视化就是用图的形式把基础数据直观&#xff0c;简洁的&#xff0c;高效的展示出来&#xff0c;今天为大家介绍一下如何使用葡萄城公司的嵌入式BI工具——Wyn商业…

Unity3d C#实现场景编辑/运行模式下3D模型XYZ轴混合一键排序功能(含源码工程)

前言 在部分场景搭建中需要整齐摆放一些物品&#xff08;如仓库中的货堆、货架等&#xff09;&#xff0c;因为有交互的操作在单个模型上&#xff0c;每次总是手动拖动模型操作起来也是繁琐和劳累。 在这背景下&#xff0c;我编写了一个在运行或者编辑状态下都可以进行一键排序…

Day12 C基础(指针进阶)

文章目录 指针修饰1.const 修饰2.void 大小端二级指针指针和数组1.指针和一维数组直接访问&#xff1a;间接访问&#xff1a; 2.指针和二维数组直接访问&#xff1a;间接访问&#xff1a; 数组指针 指针修饰 1.const 修饰 1)const int num 10; const int num 10;num 3; i…

【面试合集】说说微信小程序的实现原理?

面试官&#xff1a;说说微信小程序的实现原理&#xff1f; 一、背景 网页开发&#xff0c;渲染线程和脚本是互斥的&#xff0c;这也是为什么长时间的脚本运行可能会导致页面失去响应的原因&#xff0c;本质就是我们常说的 JS 是单线程的 而在小程序中&#xff0c;选择了 H…

Mac系统下,保姆级Jenkins自动化部署Android

一、Jenkins自动化部署 1、安装jenkins 官网&#xff1a;macOS Installers for Jenkins LTS 选择macOS brew install jenkins-lts 安装最新: brew install jenkins-lts 启动jenkins服务: brew services start jenkins-lts 重启jenkins服务: brew services restart jenkin…

YOLOv5改进系列(27)——添加SCConv注意力卷积(CVPR 2023|即插即用的高效卷积模块)

【YOLOv5改进系列】前期回顾&#xff1a; YOLOv5改进系列&#xff08;0&#xff09;——重要性能指标与训练结果评价及分析 YOLOv5改进系列&#xff08;1&#xff09;——添加SE注意力机制 YOLOv5改进系列&#xff08;2&#xff09;——添加CBAM注意力机制 YOLOv5改进系列&…

Netty-Netty源码分析

Netty线程模型图 Netty线程模型源码剖析图 Netty高并发高性能架构设计精髓 主从Reactor线程模型NIO多路复用非阻塞无锁串行化设计思想支持高性能序列化协议零拷贝(直接内存的使用)ByteBuf内存池设计灵活的TCP参数配置能力并发优化 无锁串行化设计思想 在大多数场景下&#…

如何用GPT进行论文润色与改写?

详情点击链接&#xff1a;如何用GPT/GPT4进行论文润色与改写&#xff1f;一OpenAI 1.最新大模型GPT-4 Turbo 2.最新发布的高级数据分析&#xff0c;AI画图&#xff0c;图像识别&#xff0c;文档API 3.GPT Store 4.从0到1创建自己的GPT应用 5. 模型Gemini以及大模型Claude2二…

1.16 day3 IO网络编程

用udp实现tftp下载功能 #include <myhead.h> #define PORT 69 #define IP "192.168.122.24" int xiazai(int sfd,struct sockaddr_in sin,int fd,socklen_t socklen) {char buf[516]"";char ack[4];short *p1(short *)buf;*p1htons(1);char *p2buf2…

数字化转型:为何失败率居高不下,以及如何避免重蹈覆辙

在当今快速发展的数字化时代&#xff0c;许多企业纷纷投身于数字化转型的浪潮中&#xff0c;以期通过技术革新提升竞争力、优化运营、提高效率。然而&#xff0c;尽管数字化转型的潜在益处巨大&#xff0c;但失败率却居高不下&#xff0c;甚至导致企业陷入困境。 本文将深入探讨…

Git版本控制——分支

分支 几乎所有的版本控制系统都以某种形式支持分支。 使用分支意味着可以把工作从开发主线上分离开来进行重大的Bug修改、开发新的功能&#xff0c;以免影响开发主线。 查看本地分支 git branch创建本地分支 git branch 分支名切换分支(checkout) git checkout 分支名创建…

jenkins url发生改变如何修改回来

问题&#xff1a; 我的jenkins服务器部署完后&#xff0c;此时url就已经固定了如下&#xff1a; 但是我更换了公网IP&#xff0c;url地址还是旧的&#xff0c;现在就需要修改一下配置文件&#xff1b; 修改配置文件 ($JENKINS_HOME/jenkins.model.JenkinsLocationConfiguratio…

java日志框架总结

一、日志框架简单分类介绍 java常用的日志框架、可以分为两组&#xff1a; 1、JCL、JUL、Log4j&#xff1b; 2、SLF4J、Log4j2、Logback&#xff1b; 其中第一组是比较早期的日志实现框架&#xff0c;JCL并不是具体的日志实现框架&#xff0c;JCL其实是定义了一…