微服务网关Gateway(上)

大家好呀,我是苍何。

这年头,大家都在开始卷简历了,我也看了很多同学的简历,其中有一个同学的简历,我印象最为深刻,他的项目经历中,写了自定义 Gateway 过滤器实现统计接口调用耗时,我瞬间就来兴趣了~

要知道利用微服务中的网关过滤器能力来统计接口调用耗时情况,其落地项目和设计思路是很考察对微服务架构整体掌握程度的。

那今天我们就来重点看一看微服务中的网关吧,还是以 PmHub 项目实践深入展开。

为什么需要网关

网关我觉得可以理解成是微服务系统的门卫,是微服务架构中一个关键的组件,负责管理和调控外部请求进入内部微服务的流量。为了更好理解,拿个生活中的例子来对比下:

一个大型的购物中心(微服务系统),里面有很多不同的商店(不同的微服务),比如服装店、餐馆、电影院等等。每个商店都有自己独立的入口,这样的好处是每个商店都可以独立运营。但是,如果每个顾客都直接去商店入口没有统一入口,会非常混乱。

而且,购物中心需要对每个商店的顾客流量进行管理,比如防止某些商店人满为患或者统一处理会员优惠等。

在这里插入图片描述

网关在微服务体系中的具体位置在哪儿呢?

在这里插入图片描述

可以看到,网关在负载均衡下的第一入口,也就是说,整个微服务系统,外部请求都必须要经过网关,可以说是整个系统的门卫了。那网关具体负责哪些呢?

在这里插入图片描述

总结来说,微服务的应用可能部署在不同机房,不同地区,不同域名下。此时客户端(浏览器/手机/软件工具)想要请求对应的服务,都需要知道机器的具体 IP 或者域名 URL,当微服务实例众多时,这是非常难以记忆的,对 于客户端来说也太复杂难以维护。

此时就有了网关,客户端相关的请求直接发送到网关,由网关根据请求标识解析判断出具体的微服务地址,再把请求转发到微服务实例。这其中的记忆功能就全部交由网关来操作了。

网关选型

Cloud 全家桶中有个很重要的组件就是网关,在 1.x 版本中都是采用的 Zuul 网关;但在 2.x 版本中,Zuul 的升级一直跳票,SpringCloud 最后自己研发了一个网关 SpringCloud Gateway 替代 Zuul。所以新项目,我们就别再去用 Zuul 了,简历上也最好以 Gateway 为主。

所以目前用的主流的网关就是 SpringCloud Gateway 替代 Zuul 1.x 版网关。PmHub 中采用的也是自建 SpringCloud Gateway 的方式。

Spring Cloud Gateway

Spring Cloud Gateway是基于 Spring 生态系统之上构建的 API 网关,包括:Spring 5.x,Spring Boot 2.x 和 Project Reactor。Spring Cloud Gateway 旨在提供一种简单而有效的方法来路由到 API,并为它们提供跨领域的关注点,例如:安全性,监视/指标,限流等。

以下是官方原理图:

在这里插入图片描述

Gateway 三大核心

看官网介绍可知,Spring Cloud Gateway 三大核心组件分别是路由(Route)、断言(Predicate)、过滤器(Filter),构成了网关的必要功能。

在这里插入图片描述

web 前端请求,通过一些匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。

predicate就是我们的匹配条件。

filter,就可以理解为一个无所不能的拦截器。有了这两个元素,再加上目标uri,就可以实现一个具体的路由了。

在这里插入图片描述

路由(Route)

路由是构建网关的基本模块,它由 ID,目标 URI,一系列的断言和过滤器组成,如果断言为 true 则匹配该路由。

在 PmHub 中网关的路由配置如下:

spring:
  cloud:
    gateway:
      discovery:
        locator:
          lowerCaseServiceId: true
          enabled: true
      routes:
        # 认证中心
        - id: pmhub-auth
          uri: lb://pmhub-auth
          predicates:
            - Path=/auth/**
          filters:
            # 验证码处理
            - CacheRequestFilter
           # - ValidateCodeFilter
            - StripPrefix=1
        # 代码生成
        - id: pmhub-gen
          uri: lb://pmhub-gen
          predicates:
            - Path=/gen/**
          filters:
            - StripPrefix=0

拿认证中心服务来说,id 取的就是 auth 在 nacos 注册的服务名,这样,请求网关的 URL 中带有「/auth/**」的请求都会被转发到认证中心这个服务上来。

在spring cloud gateway中配置uri有三种方式,包括

websocket配置方式

spring:
  cloud:
    gateway:
      routes:
        - id: pmhub-api
          uri: ws://localhost:9090/
          predicates:
            - Path=/api/**

http地址配置方式

spring:
  cloud:
    gateway:
      routes:
        - id: pmhub-api
          uri: http://localhost:9090/
          predicates:
            - Path=/api/**

注册中心配置方式

其中 PmHub 中采用的是这种通过 Nacos 配置中心的配置方式。

spring:
  cloud:
    gateway:
      routes:
        - id: pmhub-api
          uri: lb://ruoyi-api
          predicates:
            - Path=/api/**

断言(Predicate)

断言可以理解为是匹配规则,比如在 PmHub 中配置的「 - Path=/auth/**」就代表所有符合这个路径的规则都会被转发到对应的服务上面来。可以看下官网介绍:

在这里插入图片描述

简而言之,Predicate 就是为了实现一组匹配规则,让请求过来找到对应的Route 进行处理。

Spring Cloud Gateway 创建 Route 对象时, 使用RoutePredicateFactory 创建 Predicate 对象,Predicate 对象可以赋值给Route。

  • Spring Cloud Gateway包含许多内置的Route Predicate Factories。
  • 所有这些断言都匹配 HTTP 请求的不同属性。
  • 多个Route Predicate Factories可以通过逻辑与(and)结合起来一起使用。

路由断言工厂 RoutePredicateFactory 包含的主要实现类如图所示,包括Datetime、请求的远端地址、路由权重、请求头、Host 地址、请求方法、请求路径和请求参数等类型的路由断言。

在这里插入图片描述

当然了除了我们定义的规则,也是可以支持一下路由规则的自定义的,以下是一些常用的断言。

Weight-匹配权重

spring: 
  application:
    name: pmhub-gateway
  cloud:
    gateway:
      routes:
        - id: pmhub-system-a
          uri: http://localhost:9201/
          predicates:
            - Weight=group1, 8
        - id: pmhub-system-b
          uri: http://localhost:9201/
          predicates:
            - Weight=group1, 2

Datetime-匹配日期时间之后发生的请求

spring: 
  application:
    name: pmhub-gateway
  cloud:
    gateway:
      routes:
        - id: pmhub-system
          uri: http://localhost:9201/
          predicates:
            - After=2021-02-23T14:20:00.000+08:00[Asia/Shanghai]

Query-匹配查询参数

spring: 
  application:
    name: pmhub-gateway
  cloud:
    gateway:
      routes:
        - id: pmhub-system
          uri: http://localhost:9201/
          predicates:
            - Query=username, abc.

Path-匹配请求路径

spring: 
  application:
    name: pmhub-gateway
  cloud:
    gateway:
      routes:
        - id: pmhub-system
          uri: http://localhost:9201/
          predicates:
            - Path=/system/**

Header-匹配具有指定名称的请求头,

\d+值匹配正则表达式

spring: 
  application:
    name: pmhub-gateway
  cloud:
    gateway:
      routes:
        - id: pmhub-system
          uri: http://localhost:9201/
          predicates:
            - Header=X-Request-Id, \d+

当然了,内置的模板不满足需求,也是可以自定义断言规则的,方法也比较简单,按照以下套路即可:

  • 要么继承 AbstractRoutePredicateFactory 抽象类
  • 要么实现 lRoutePredicateFactory:接口
  • 类开头任意取名,但是必须以 RoutePredicateFactory 后缀结尾

如下代码:

/**
 * @auther canghe
 * @create 2024-05-23 18:30
 */
@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config>
{
    public MyRoutePredicateFactory()
    {
        super(MyRoutePredicateFactory.Config.class);
    }

    @Validated
    public static class Config{
        @Setter
        @Getter
        @NotEmpty
        private String userType; //钻、金、银等用户等级
    }

    @Override
    public Predicate<ServerWebExchange> apply(MyRoutePredicateFactory.Config config)
    {
        return new Predicate<ServerWebExchange>()
        {
            @Override
            public boolean test(ServerWebExchange serverWebExchange)
            {
                //检查request的参数里面,userType是否为指定的值,符合配置就通过
                String userType = serverWebExchange.getRequest().getQueryParams().getFirst("userType");

                if (userType == null) return false;

                //如果说参数存在,就和config的数据进行比较
                if(userType.equals(config.getUserType())) {
                    return true;
                }

                return false;
            }
        };
    }
}

过滤器(Filter)

网关中的过滤器,有点类似 SpringMVC 里面的拦截器 Interceptor 以及 Servlet 的过滤器,其中「pre」 和「post」分别会在请求被执行钱调用和被执行后调用,用来修改请求和响应信息。

过滤器也是面试中最常问的知识点,比如记录接口调用市场统计、限流、黑白名单等。

因文章篇幅有限,将在下一章单独细说细说,可见其重要程度了,也是 PmHub 项目框架的核心之一了。感兴趣可以持续关注。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Hive SQL 每日一题】统计各个商品今年销售额与去年销售额的增长率及排名变化

文章目录 测试数据需求说明需求实现分步解析 测试数据 -- 创建商品表 DROP TABLE IF EXISTS products; CREATE TABLE products (product_id INT,product_name STRING );INSERT INTO products VALUES (1, Product A), (2, Product B), (3, Product C), (4, Product D), (5, Pro…

什么是研学活动?快速了解

说起什么是研学活动&#xff0c;其实就是一种结合学习与实地考察、体验的教育方式&#xff0c;旨在通过实践活动深化学生对课堂知识的理解和应用&#xff0c;培养学生的综合素质和创新能力。让学生在亲身体验中学习和成长。当学校宣布即将组织一次研学活动时&#xff0c;孩子们…

如何批量复制文件名?文件名批量提取的5个工具!(2024新)

在数字化时代&#xff0c;我们经常需要处理大量的文件&#xff0c;其中批量复制文件名或批量提取文件名成为一项常见的任务。这不仅可以提高我们的工作效率&#xff0c;还能使文件管理更为有序。本文将介绍五种2024年最新的文件名批量提取工具&#xff0c;帮助你轻松完成文件名…

手把手教你从0到1开发浏览器插件

使用Chrome插件可以为Chrome浏览器带来一些功能性的扩展&#xff0c;进而提高使用体验&#xff1b;俗话说的好Chrome没插件&#xff0c;香味少一半&#xff0c;Chrome最大的优势还是其支持众多强大好用的扩展程序&#xff1b;今天就来了解一下插件是如何开发的&#xff0c;和普…

C语言基础——数组(2)

ʕ • ᴥ • ʔ づ♡ど &#x1f389; 欢迎点赞支持&#x1f389; 个人主页&#xff1a;励志不掉头发的内向程序员&#xff1b; 专栏主页&#xff1a;C语言基础&#xff1b; 文章目录 前言 一、二维数组的创建 1.1 二维数组的概念 1.2二维数组的创建 二、二维数组…

MySQL中获取时间的方法

大家好&#xff0c;在MySQL数据库开发中&#xff0c;获取时间是一个常见的需求。MySQL提供了多种方法来获取当前日期、时间和时间戳&#xff0c;并且可以对时间进行格式化、计算和转换。 以下是一些常用的MySQL时间函数及其示例&#xff1a; 1、NOW()&#xff1a;用于获取当前…

汇舟问卷:国外问卷调查怎么样?

互联网的发展为我们提供了无数的赚钱机会&#xff0c;其中不乏一些投资小、易上手的小项目&#xff0c;可以让大家充分的利用起业余的时间&#xff0c;赚到日常工作之外的收入。 ​这些项目不仅操作简单&#xff0c;而且时间灵活&#xff0c;非常适合想要利用闲余时间赚外快的…

云渲染农场什么是线程模式?

许多设计师在选择云渲染农场时&#xff0c;常常会遇到48线程、56线程、72线程等选项&#xff0c;然而&#xff0c;不少新手在面对这些选择时&#xff0c;往往无法直观地感受到不同线程数量之间的差异。接下来&#xff0c;我们将共同探讨线程的作用和影响&#xff0c;帮助大家更…

生产制造过程中操作人员引起的不稳定性

获取更多资讯&#xff0c;赶快关注上面的公众号吧&#xff01; 文章目录 工艺成熟度操作成熟度 生产制造过程中&#xff0c;操作人员可能引起一些生产不稳定性&#xff0c;本文将主要介绍两类。 工艺成熟度 以前在工厂做项目时&#xff0c;明明都已经是可全部自动化的高级数…

1347:【例4-8】格子游戏

【解题思路】 该题为判断无向图是否有环。可以使用并查集来完成。学习并查集时&#xff0c;每个元素都由一个整数来表示。而该问题中每个元素是一个坐标点&#xff0c;由(x, y)两个整数构成。 将二维坐标变为一个整数,通过一个公式将二维坐标换算为一个整数&…

如何不用口吐莲花,照样成为社交达人

一、教程描述 每个人的一生&#xff0c;70%的时候都在沟通&#xff0c;与老板沟通、与家人沟通、与朋友沟通、与陌生人沟通&#xff0c;等等&#xff0c;但是你真的会沟通么&#xff1f;不论是工作上跟上司、同事和客户间的沟通&#xff0c;还是生活中与家人、朋友、伴侣间的沟…

B端产品无爆款,说有的都是忽悠和外行!

前言&#xff1a;网上经常有人讲运营&#xff0c;把C端那一套硬搬到B端&#xff0c;讲的自我陶醉&#xff0c;稍微有点常识的人就知道不能这么玩。 一、什么是B端和C端 B端&#xff08;Business-to-Business&#xff09;是指面向企业客户的市场和产品。B端产品或服务主要是为…

kafka命令--简单粗暴有效

zookeeper bin目录下执行 启动&#xff1a;./zkServer.sh start 停止&#xff1a;./zkServer.sh stop 重启&#xff1a;./zkServer.sh restart 状态&#xff1a;./zkServer.sh status kafka bin目录下执行 启动&#xff1a;./kafka-server-start.sh -daemon …/config/server.…

【excel】设置可变下拉菜单(一级联动下拉菜单)

文章目录 【需求】制作动态下拉菜单&#xff0c;显示无重复的“班级”列表【思路】设置辅助列&#xff0c;使用UNIQUE()函数去重&#xff0c;并用FILTER()去掉结果中的“0”【步骤】step1 辅助列step2 设置下拉菜单 【总结】 在这个一级下拉菜单后&#xff0c;我又写了二级联动…

【十年java搬砖路】Jumpserver docker版安装及配置Ldap登陆认证

Jumpserver docker 安装启动教程 拉取镜像 docker pull JumpServer启动进行前确保有Redis 和Mysql 创建jumperServer数据库 在MYSQL上执行 创建数据库 登陆MYSQL mysql -u root -p 创建Jumperserveri库 create database jumpserver default charset utf8mb4;可以为jumperSe…

PTA输入字符串str,识别字符串中字符(0-9A-Za-z),并对识别出的字符串按照按升序进行排序。

输入字符串str&#xff0c;识别字符串中指定范围内的字符(0-9A-Za-z)构成新的字符串str2&#xff0c;对字符串str2按照按升序进行排序。 输入格式: fafOgerPNM-mgg<6254 输出格式: 2456MNOPaeffgggmr #include<stdio.h> #include<string.h> int main() {cha…

SiT : Self-supervised vision Transformer

从NLP Transformer中借鉴而来的视觉 Transformer 在使用大规模监督数据或某种形式的协同监督&#xff08;例如教师网络&#xff09;进行预训练时已被证明是有效的。这些经过监督预训练的视觉Transformer在下游任务中通过最小的改动就能取得出色的结果。 随着监督预训练&#x…

springboot + Vue前后端项目(第十四记)

项目实战第十三记 写在前面1. 建立字典表2. 后端DictController3. Menu.vue4. 建立sys_role_menu中间表5.分配菜单接口6. 前端Role.vue改动总结写在最后 写在前面 本篇主要讲解动态分配菜单第二章节 菜单页面优化 引入图标 角色界面优化 角色自主分配菜单&#xff0c;并保存至…

PTA字符串str1在第i个位置插入字符串str2

字符串str1在第i个位置插入字符串str2&#xff0c;如在字符串1234567890第2位插入ABC。 输入格式: 1234567890 ABC 2 输出格式: 12ABC34567890 #include<stdio.h> #include<string.h> int main() {char s1[100],s2[100];int w;scanf("%s%s%d",s1,s2,…

Docker 基础使用(2) 镜像与容器

文章目录 镜像的含义镜像的构成镜像的作用镜像的指令容器的含义容器的状态容器的指令 Docker 基础使用&#xff08;0&#xff09;基础认识 Docker 基础使用 (1) 使用流程概览 Docker 基础使用&#xff08;2&#xff09; 镜像与容器 Docker 基础使用&#xff08;3&#xff09; 存…