Spring Cloud Gateway 服务网关的部署与使用详细介绍

news2025/1/15 13:39:42

为什么需要服务网关

传统的单体架构中只需要开放一个服务给客户端调用,但是微服务架构中是将一个系统拆分成多个微服务,如果没有网关,客户端只能在本地记录每个微服务的调用地址,当需要调用的微服务数量很多时,它需要了解每个服务的接口,这个工作量很大。有了网关之后,网关作为系统的唯一流量入口,封装内部系统的架构,所有请求都先经过网关,由网关将请求路由到合适的微服务。

使用网关的好处

1)简化客户端的工作。网关将微服务封装起来后,客户端只需同网关交互,而不必调用各个不同服务;
(2)降低函数间的耦合度。 一旦服务接口修改,只需修改网关的路由策略,不必修改每个调用该函数的客户端,从而减少了程序间的耦合性
(3)解放开发人员把精力专注于业务逻辑的实现。由网关统一实现服务路由(灰度与ABTest)、负载均衡、访问控制、流控熔断降级等非业务相关功能,而不需要每个服务 API 实现时都去考虑

Gateway网关的demo

8001端口的服务,然后他有以下两个接口,但是我又不想让别人通过8001端口访问,我想让他通过9527访问怎么办?很简单通过Gateway搭建一个网关服务即可解决该问题。

@RestController
@Slf4j
public class PaymentController {

    @Autowired
    private PaymentMapper paymentMapper;

    @Value("${server.port}")
    private String serverPort;

    @GetMapping(value = "/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {
        Payment payment = paymentMapper.selectById(id);
        log.info("*****查询结果:{}", payment);
        if (payment != null) {
            return new CommonResult(200, "查询成功, 服务端口:" + serverPort, payment);
        } else {
            return new CommonResult(444, "没有对应记录,查询ID: " + id + ",服务端口:" + serverPort, null);
        }
    }

    @GetMapping(value = "/payment/lb")
    public String getPaymentLB() {
        return serverPort;
    }
}

接下来搭建一个9527端口的Gateway入门级别的网关服务

1、以下是使用到的核心依赖,一般都会采用聚合工程,由父工程存放dependencyManagement当中的依赖,其他子模块引入使用的组件即可,单纯的练习图省劲的话,创建一个独立可运行的boot项目也可以。

<dependencyManagement>
    <dependencies>
        <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-dependencies</artifactId>
           <version>2.6.8</version>
           <type>pom</type>
           <scope>import</scope>
       </dependency>
        <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-dependencies</artifactId>
           <version>2021.0.3</version>
           <type>pom</type>
           <scope>import</scope>
       </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <!--gateway-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
 </dependencies>   

2, 添加配置

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
      - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
        uri: http://localhost:8001          #匹配后提供服务的路由地址
        predicates:
        - Path=/payment/get/**         # 断言,路径相匹配的进行路由

      - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
        uri: http://localhost:8001          #匹配后提供服务的路由地址
        predicates:
        - Path=/payment/lb/**         # 断言,路径相匹配的进行路由

3、测试访问:http://localhost:9527/payment/get/1

在这里插入图片描述
在这里插入图片描述

Gateway三大核心概念

Route(路由)

路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由。
请求从外面过来,会先被网关处理,网关会决定该请求会调用哪个微服务,但是这个请求怎么调用呢?所以网关是不是必须要有一个路由器啊,它要可以进行请求的路由转发,具体决定该请求会调用哪个微服务。

Predicate(断言)

是什么

启动网关服务的时候会发现有一排日志,如下所示:
在这里插入图片描述
首先我们会发现一共有12个 RoutePredicateFactorie,他们每个都有自己的应用场景

作用

如果请求与断言相匹配则进行路由,如果不匹配直接404

路由断言规则

在这里插入图片描述

时间作为匹配路由规则

  1. After
    当请求的时间在断言时间之后,将匹配路由
    也就是我们下面配置的时间 2022-03-20T21:02:47.789 之后可以成功匹配路由,之前匹配失败
spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest          # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8080  # 匹配后提供服务的路由地址
          predicates:
            - After=2022-03-20T21:02:47.789-07:00[Asia/Shanghai]

当请求的时间在断言时间之后,将匹配路由
也就是我们配置的时间 2022-03-20T21:02:47.789 之后可以成功匹配路由

  1. Before
    与After正好相反

  2. Between
    指定两个时间,用逗号分割,如果请求时间在这两个时间之间,将匹配路由

server:
  port: 81
spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest          # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8080  # 匹配后提供服务的路由地址
          predicates:
            - Between=2022-03-19T21:02:47.789-07:00[Asia/Shanghai],2022-03-22T21:02:47.789-07:00[Asia/Shanghai]

Cookie作为匹配路由规则

server:
  port: 81
spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest          # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8080  # 匹配后提供服务的路由地址
          predicates:
            - Cookie=token,123

如果请求cookie中有name为token,且值为123将匹配当前路由
name和value有一个不一样都不能成功路由
name和value都相同 则能成功路由
在这里插入图片描述

在这里插入图片描述

请求头作为匹配路由规则 Header

server:
  port: 81
spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest          # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8080  # 匹配后提供服务的路由地址
          predicates:
            - Header=token,123

请求对象的请求头中 如果有name为token,且值为123,将匹配当前路由

在这里插入图片描述

如图 测试请求头没有name为token value为123 的请求头信息 则不能匹配路由

在这里插入图片描述

当请求头中有 name为token 值为 123的请求头信息时,能匹配到当前路由

Host作为匹配路由规则 Host

server:
  port: 81
spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest          # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8080  # 匹配后提供服务的路由地址
          predicates:
            - Host=**.haha.com:81

请求方法作为匹配路由规则 Method

server:
  port: 81
spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest          # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8080  # 匹配后提供服务的路由地址
          predicates:
            - Method=GET,POST

上面的请求GET和POST请求都能匹配到路由,如果我们换成PUT请求则不能匹配到路由

路径作为匹配路由规则 Path

server:
  port: 81
spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest          # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8080  # 匹配后提供服务的路由地址
          predicates:
            - Path=/say

上面的案例访问 /say 能匹配到路由
多加一级路径则不能匹配到路由
可以正则 改成 /say/**
此时无论访问 /say 还是 /say/one都能匹配到路由

查询参数作为匹配路由规则 Query

server:
  port: 81
spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest          # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8080  # 匹配后提供服务的路由地址
          predicates:
            - Query=skuID

如果只写一个参数 则意思为 查询参数有skuID则匹配当前路由
在这里插入图片描述

server:
  port: 81
spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest          # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8080  # 匹配后提供服务的路由地址
          predicates:
            - Query=skuID,11

如果两个参数,用逗号分割 则意思为 查询参数为skuID ,且值为11 匹配当前路由

注意 两个条件都必须满足 且请求方式与服务请求映射的方式一致

如果skuID 不为 11 也不能匹配到当前路由

权重作为匹配路由规则 Weight

server:
  port: 81
spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest1         # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:80  # 匹配后提供服务的路由地址
          predicates:
            - Path=/say/**
            - Weight=group,5
        - id: apptest2          # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8081  # 匹配后提供服务的路由地址
          predicates:
            - Path=/say/**
            - Weight=group,5

Filter(过滤)

过滤器可以在执行方法前和执行方法后进行过滤,所谓的过滤就是可以在请求上加一些操作,例如匹配到路由后可以在请求上添加个请求头,或者参数等等。

Gateway过滤器分为了两种:路由过滤器 和 全局过滤器

路由过滤器

全局过滤器

全局过滤器的作用是处理一切进入网关的请求和微服务响应,与GatewayFilter的作用一样。区别在于GatewayFilter通过配置定义,处理逻辑是固定的;而GlobalFilter的逻辑需要自己写代码实现。

自定义全局过滤器(Filter)

Gateway内部有一个接口 名为GlobalFilter,这个就是Gateway的全局过滤器接口,只要在应用中实现此接口后注册为Spring的Bean,它就会就会帮我们将这个实现注册到全局过滤器链条里边去
在这里插入图片描述
测试:

请求中必须要包含uname请求参数,那么才会进行路由转发,否则不会进行路由转发,如下图:
在这里插入图片描述
在这里插入图片描述

过滤器的执行顺序

过滤器会被执行两次,过滤分为pre和post。

pre:请求前调用。
post:响应结果返回时调用,顺序和pre完全相反。

请求进入网关会碰到三类过滤器:当前路由的过滤器、DefaultFilter、GlobalFilter

请求路由后,会将当前路由过滤器和DefaultFilter、GlobalFilter,合并到一个过滤器链(集合)中,排序后依次执行每个过滤器:
在这里插入图片描述
排序规则如下:

每一个过滤器都必须指定一个int类型的order值,order值越小,优先级越高,执行顺序越靠前。
GlobalFilter通过实现Ordered接口,或者添加@Order注解来指定order值,由我们自己指定
路由过滤器和defaultFilter的order由Spring指定,默认是按照声明顺序从1递增。
当过滤器的order值一样时,会按照 defaultFilter > 路由过滤器 > GlobalFilter的顺序执行。

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

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

相关文章

【音视频第20天】wireshark+tcpdump

tcpdump抓 wireshark分析 目录 tcpdumpwireshark tcpdump tcpdump参数详解 网上一搜一大堆。最全的不是用tcpdump -h而是man tcpdump来查询手册。 tcpdump -i eth0 -p udp -xx -Xs 0 -w /root/test2.cap -i 针对eth0网卡的&#xff0c;ifconfig是查看有几个网卡 -i eth0 表示…

海睿思分享 | 终于有人把指标体系和标签体系说清楚了

当前&#xff0c;随着企业数字化转型如火如荼地开展&#xff0c;在企业经营管理数字化的数据建设过程中&#xff0c;经常会遇到指标和标签的使用场景。 指标体系到底是什么&#xff1f;标签体系又是什么&#xff1f;这些疑问导致在数据分析过程中效率低下、科学性不高&#xf…

回首来路多感概,最是奋斗动人心。

我们必需要在不同的时代有不同的领悟&#xff0c;才能充满生机地去迎接生命中每个新的开始。 文章目录 前言 初心 成长 收获 憧憬 出发 前言 今天是我成为csdn创作者一周年纪念日&#xff0c;我非常开心能够和大家分享我的写作之旅。在这一年里&#xff0c;我经历了许多挑…

ChatGPT实现数据集模拟生成,ChatGPT实现密码生成

数据集模拟生成 之前章节我们已经演示过ChatGPT 如何根据 prompt 编写文章或续写文章&#xff0c;文本生成的作用不仅仅在语文方面有用&#xff0c;本节我们演示另一种场景&#xff0c;利用 ChatGPT 来生成数据。看似作用差不多&#xff0c;其实这是目前开源社区非常常用的大语…

低代码和零代码二子争夺,你扶谁上位?

传统的软件研发方式目前并不能很好地满足企业的需求&#xff1a;人员成本高、研发时间长、运维复杂。这时低代码或零代码工具的出现为快速开发软件提供了更好的思路。对于不太了解两者的人来说&#xff0c;零代码和低代码是什么&#xff1f;又有什么联系与区别&#xff1f; 什么…

手把手教你安装telnet(离线方式+在线方式)

系列文章目录 文章目录 系列文章目录前言一、telnet是什么&#xff1f;二、安装步骤总结 前言 一、telnet是什么&#xff1f; Telnet协议是TCP/IP协议族中的一员&#xff0c;是Internet远程登录服务的标准协议和主要方式。它为用户提供了在本地计算机上完成远程主机工作的能力…

[openwrt] valgrind定位内存泄漏

目录 要求 valgrind 简介 工具介绍 linux程序的内存布局 内存检查的原理 valgrind的使用 使用举例 内存泄漏 内存越界 内存覆盖 Linux分配虚拟内存&#xff08;申请内存&#xff09;的两种方式 brk和mmap 要求 被调试程序带有-g参数编译&#xff0c;携带debug参数…

二维码在数字化班组管理中的应用

为了更好地贯彻落实集团公司对班组安全建设的要求&#xff0c;可以运用“加法思维”&#xff0c;勇于直面当前安全班组建设中的突出问题&#xff0c;敢于创新和突破&#xff0c;自主搭建数字化班组管理平台&#xff0c;以进一步提升班组安全建设水平。 本文将详细介绍搭建设备…

腾讯云CDN的HTTPS服务是收费的?

腾讯云内容分发网络CDN的HTTPS请求数收费了&#xff0c;之前阿里云CDN是收费的&#xff0c;现在腾讯云HTTPS请求数也开始收费的&#xff0c;但是腾讯云还是很良心的每月300万次以内是不计费的&#xff0c;只有超出free额度的部分才另外收费&#xff0c;HTTPS请求数价格为0.05元…

Windows10资源管理器使用

文章目录 前言二、关联菜单操作1.分组展示2.添加选择复选框3.使用窗格模式4.功能区折叠二、“文件夹选项”对话框操作1.访问模式调整2.状态栏控制总结前言 目前Windows系统中的使用较多当属Windows10,资源管理器属于Windows系统中一个常用工具。本文总结了Windows 10 专业版下…

类的默认成员函数

为什么会有构造函数和析构函数呢&#xff1f; 1、初始化和销毁经常忘记 2、有些地方写起来很繁琐. Stack有了构造和析构&#xff0c;就不怕忘记写初始化和清理函数了&#xff0c;也简化了 例如在队列oj时&#xff0c;忘记释放&#xff0c;造成内存泄漏 构造函数 主要任务&am…

spark on k8s 部署的一点理解

Running Spark on Kubernetes - Spark 3.4.0 Documentation (apache.org) 前提条件 1. 本地有spark安装包&#xff0c;以便于执行 spark submit 命令 2. k8s 集群&#xff0c;以及本地的有 kubectl 并且配置的用户包含相关权限&#xff0c;具体可以参考官网 一些观念的转变 …

二百左右的蓝牙耳机哪款好?200左右音质最好的蓝牙耳机

在日常生活中离不开智能手机&#xff0c;特别是对无线蓝牙耳机的需求程度也越来越高&#xff0c;但是市面上有很多的蓝牙耳机戴久了耳朵会出现不舒服&#xff0c;为了获得更好的使用体验&#xff0c;我整理了市面上200左右价位佩戴和音质都表现不错的蓝牙耳机。 一、南卡小音舱…

Leetcode 并查集详解

在一些应用的问题中&#xff0c;需将n个不同的元素划分成一组不相交的集合。开始时&#xff0c;每个元素自成一格单元素集合&#xff0c;然后按一定顺序将属于同一组的元素的集合合并。其间要反复用到查询某个元素属于哪个集合的运算。适合于描述这类问题的抽象数据类型称为并查…

【22】linux进阶——文本处理工具:cut、awk、sed

大家好&#xff0c;这里是天亮之前ict&#xff0c;本人网络工程大三在读小学生&#xff0c;拥有锐捷的ie和红帽的ce认证。每天更新一个linux进阶的小知识&#xff0c;希望能提高自己的技术的同时&#xff0c;也可以帮助到大家 另外其它专栏请关注&#xff1a; 锐捷数通实验&…

一段凄惨Android 面试经历分享,败在了项目架构原理上……

大家应该看过很多分享面试成功的经验&#xff0c;但根据幸存者偏差的理论&#xff0c;也许多看看别人面试失败在哪里&#xff0c;对自己才更有帮助。 这是一位网友分享的面试经历&#xff0c;他准备了3个月&#xff0c;刚刚参加完字节跳动的第三面&#xff0c;视频面&#xff…

数说故事联合中山大学国际关系学院共建「国关数据实验室」,深化数据科学与国际关系融合创新

4月9日&#xff0c;数说故事联合中山大学国际关系学院共建的「国关数据实验室」正式启动&#xff0c;此次强强联合是双方在国际关系领域的一项创新尝试&#xff0c;该实验室旨在整合数说故事和国际关系学院师生的资源优势&#xff0c;将数据科学与国际关系研究相结合&#xff0…

真实还原美团4面经历,低学历成功拿到20K Offer...

个人背景 如标题所示&#xff0c;我的个人背景非常简单&#xff0c;软件测试经验 1 年半&#xff0c;学历普通&#xff0c;2 本毕业后出来就一直在做功能测试&#xff0c;在公司每天重复的工作对我的技术提升并没有什么帮助&#xff0c;但小镇出来的我也深知自我努力的重要性&…

Binder 与 四大组件工作原理 其一

Binder Binder的组成结构 Binder的架构如图所示 ServiceManager负责把Binder Server注册到一个容器中。 我们可以这样理解Client、Server 、ServiceManager、Binder Driver之间的关系&#xff1a; 把ServiceManager比喻成电话局&#xff0c;存储着每个住宅的座机电话。张三给…

记录-Vue移动端日历设计与实现

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 工作中遇到一个需求是根据日历查看某一天/某一周/某一月的睡眠报告&#xff0c;但是找了好多日历组件都不是很符合需求&#xff0c;只好自己手写一个日历组件&#xff0c;顺便记录一下。 先看看UI给的…