spring cloud 之 gateway

news2024/11/18 17:41:47

网关介绍

在微服务架构体系中,一个系统会被拆分为很多个微服务,那么作为客户端要如何去调用这么多的微服务呢?如果没有网关的存在,我们只能在客户端记录每个微服务的地址,然后分别调用,当然这样是不现实的

现有网关介绍

Kong

   基于Nginx+Lua开发,性能高,稳定,有多个可用的插件(限流、鉴权等等)可以开箱即用,只支持http调用

Zuul

 Netflix开源的网关,功能丰富,使用JAVA开发,易于二次开发,性能不如nginx

Spring Cloud Gateway

Spring公司为了替换Zuul而开发的网关服务,spring Cloud Gateway是Spring公司基于Spring 5.0,Spring Boot 2.0 和 Project Reactor ,webFlux,底层基于Netty等技术开发的网关,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能

前置知识请参考本专栏webFlux 或者传送门

网关的作用

1、能针对客户端提供统一入口(类似于守门员、门卫)

2、实现统一鉴权

3、实现流量控制

4、实现服务熔断降级 

Spring Cloud Gateway的核心概念

路由Route

是 gateway 中最基本的组件之一,路由是网关的基本单元,由ID、URI、一组Predicate、一组Filter组成,根据Predicate进行匹配转发,具体包含如下信息:

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

列举一下配置:

routes:
  # 路由的名字
  - id: cloud-test-service
  # lb指的是从nacos中按照名称获取微服务,并遵循负载均衡策略
    uri: lb://cloud-test-service
  # 断言符合这个规定的才进行1转发
    predicates:
      - Path=/common/**
    filters:
      # 将第一层去掉
      - StripPrefix=1
      # 这里使用内置的过滤器,修改返回状态
      - SetStatus=2000

转发规则 

Predicate(谓语、断言)  路由转发的判断条件,目前SpringCloud Gateway支持多种方式,常见如:Path、Query、Method、Header等,写法必须遵循 key=vlue的形式  
Filter(过滤器)过滤器是路由转发请求时所经过的过滤逻辑,可用于修改请求、响应内容

Predicate 就是为了实现一组匹配规则,方便让请求过来找到对应的 Route 进行处理,接下来我们接下 Spring Cloud GateWay 内置几种 Predicate 的使用

规则实例 说明
Path  - Path=/gate/,/rule/当请求的路径为gate、rule开头的时,进行转发
Before - Before=2017-01-20T17:42:47.789-07:00[America/Denver] 在某个时间之前的请求才会被转发
After- After=2017-01-20T17:42:47.789-07:00[America/Denver] 在某个时间之后的请求才会被转发
Between- Between=2017-01-20T17:42:47.789-07:00[America/Denver],2017-01-21T17:42:47.789-07:00[America/Denver] 在某个时间段之间的才会被转发
Cookie - Cookie=chocolate, ch.p名为chocolate的表单或者满足正则ch.p的表单才会被匹配到进行请求转发
Header - Header=X-Request-Id, \d+ 携带参数X-Request-Id或者满足\d+的请求头才会匹配
Host - Host=www.sltech.com当主机名为www.sltech.com的时候,转发
Method - Method=GET只有GET方法才会匹配转发请求,还可以限定POST、PUT等请求方式
server:
  port: 8080
spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: https://example.org
        predicates:
        - Query=smile

 这样配置,只要请求中包含 smile 属性的参数即可匹配路由

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: https://www.baidu.com
          order: 0
          predicates:
            - Host=**.foo.org
            - Path=/headers
            - Method=GET
            - Header=X-Request-Id, \d+
            - Query=foo, ba.
            - Query=baz
            - Cookie=chocolate, ch.p

 路由断言规则可以组合使用

 过滤器

过滤器规则

过滤规则实例 说明
PrefixPath- PrefixPath=/app在请求路径前加上app
RewritePath- RewritePath=/test, /app/test访问localhost:10010/test,请求会转发到localhost:10010/app/test
SetPath  SetPath=/app/{path} 通过模板设置路径,转发的规则时会在路径前增加app,{path}表示原请求路径
RedirectTo- RedirectTo=303, https://acme.org重定向定义返回码和地址
RemoveRequestHeader - RemoveRequestHeader=X-Request-Foo去掉请求头信息 X-Request-Foo

举一个例子,不一一列举 :

spring:
  cloud:
    gateway:
      routes:
      - id: removerequestheader_route
        uri: https://example.org
        filters:
        - RemoveResponseHeader=X-Request-Foo

PRE: 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择 请求的微服务、记录调试信息等

POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等

Gateway 的Filter从作用范围可分为两种: GatewayFilter与GlobalFilter:    

  • GatewayFilter:应用到单个路由或者一个分组的路由上。
  • GlobalFilter:应用到所有的路由上

过滤器生效顺序

        GlobalFilter 的功能其实和 GatewayFilter 是相同的,只是 GlobalFilter 的作用域是所有的路由配置,而不是绑定在指定的路由配置上。多个 GlobalFilter 可以通过 @Order 或者 getOrder() 方法指定执行顺序,order值越小,执行的优先级越高。

        由于过滤器分为 pre 和 post 两种类型,pre 类型过滤器如果 order 值越小,那么它就应该在pre过滤器链的顶层,post 类型过滤器如果 order 值越小,那么它就应该在 post 过滤器链的底层:

Spring Cloud Gateway的搭建及过滤器实现

项目搭建

新建springBoot项目,版本2.3.5.RELEASE,我这里cloud版本是Hoxton.SR12

<dependencies>
        <!-- 网关依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!--nacos客户端依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--feign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

</dependencies>

添加配置 

server:
  port: 10010
spring:
  application:
    name: could-gateway-server
# 必须加这句话,让gateway可以发现注册中心的服务
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        # 路由的名字
        - id: cloud-test-service
        # lb指的是从nacos中按照名称获取微服务,并遵循负载均衡策略
          uri: lb://cloud-test-service
        # 断言符合这个规定的才进行1转发
          predicates:
            - Path=/common/**
          filters:
            # 将第一层去掉
            - StripPrefix=1
            # 这里使用内置的过滤器,修改返回状态
            - SetStatus=2000
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

添加过滤器 

局部过滤器

局部过滤器需要继承AbstractGatewayFilterFactory,重写apply方法,过滤器名称必须叫xxxGatewayFilterFactory,配置的路由的时候可以直接配置xxx

import lombok.Data;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
 
@Component
public class myParamGateWayFilterFactory extends AbstractGatewayFilterFactory<MyCustomLocalFiterFactory.ParamsConfig> {
    @Override
    public String name() {
        return "mycustomlocalfiter";
    }
 
    public MyCustomLocalFiterFactory() {
        super(ParamsConfig.class);
    }
 
    @Override
    public GatewayFilter apply(ParamsConfig config) {
        return (exchange, chain) -> {
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                System.out.println("name=" + config.getParamName() + ";value=" + config.getParamValue());
            }));
        };
    }
 
 
    @Data
    public static class ParamsConfig {
        private String paramName;
 
        private String paramValue;
 
    }
}

应用到路由上

     filters: 
            - StripPrefix=1
            - name: myParam
              args:
                paramname: "this is paramName"
                paramvalue: "this is paramValue"

全局过滤器 

全局过滤器交给spring容器管理,无需任何配置即可生效,全局过滤器针对所有路由有效,

注意:写在then之中的是后置逻辑,见下方示例: 
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
 {
       log.info("BFilter前置逻辑");
       return chain.filter(exchange).then(Mono.fromRunnable(() ->
        {
             log.info("BFilter后置逻辑");
        }));
}

前置过滤器

@Component
public class MyCustomGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("this is custom pre filter");
        return chain.filter(exchange).then();
    }
 
    @Override
    public int getOrder() {
        return 0;
    }
}

后置过滤器

@Component
public class MyCustomGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 写在then中
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            System.out.println("this is post filter");
        }));
    }
 
    @Override
    public int getOrder() {
        return 0;
    }
}


 

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

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

相关文章

Mysql事务原理

一、概述 事务&#xff1a;一组操作要么全部成功&#xff0c;要么全部失败&#xff0c;目的是为了保证数据最终的一致性。 数据库一般都会并发执行多个事务&#xff0c;多个事务可能会并发的对相同的一批数据进行增删改查操作&#xff0c;可能就会导致我们说的脏写、脏读、不可…

水站桶装水订水系统桶装水小程序,改变了桶装水行业传统的送水模式;

水站桶装水订水系统桶装水小程序&#xff0c;改变了桶装水行业传统的送水模式&#xff0c;客户通过线上下单&#xff0c;送水工实时接单配送&#xff0c;空桶更好的记录管理&#xff0c;财务数据在后台清晰明了&#xff0c;提高了水站的工作效率。 除此之外&#xff0c;还有很多…

网络系统集成实验(五)| 系统集成路由器OSPF动态、综合路由配置

一、前言 该系列文章将会对网络系统集成课程中相关实验进行更新&#xff0c;本篇为第五篇&#xff0c;有关路由器的OSPF、综合路由配置&#xff0c;包括了OSPF的配置实验、单臂路由实验、RIP配置实验、综合实验等。 注意&#xff1a;该实验的后半部分综合实验基于前面的实验&am…

java Collection集合使用笔记

1、Collection集合概述 它是单例集合的最顶层接口&#xff0c;它表示一组对象&#xff0c;这些对象也称之为Collection的元素JDK不提供此接口任何直接实现&#xff0c;但提供更具体的子接口&#xff08;如&#xff1a;List和Set&#xff09;实现创建Collection集合对象的方法&…

麒麟信安与飞腾携手共赴云端

当前各行业已进入全面云化时代&#xff0c;云桌面技术作为典型办公终端替代方案&#xff0c;凭借其数据安全、便捷运维、综合成本占优的优势正逐步在各行业应用实施。伴随十四五规划加速数字化转型及信息产业核心技术自主化发展&#xff0c;各政企组织迫切需要基于国产软硬件实…

gmap构建离线地图,用createCustomerTiledLayer方法,瓦片地址尾部多了 ?x={x}y={y}z{z} 导致无法显示地图。

gmap构建离线地图&#xff0c;用createCustomerTiledLayer方法&#xff0c;瓦片地址尾部多了 ?x{x}&y{y}&z&{z} 导致无法显示地图。 function initMap() {this.map new GL.Map(map, {center: "120.650847,31.3092434",zoom: 12,zoomControl: false,sca…

青大数据结构【2018】【算法设计】

关键词&#xff1a; 单链表递增、树的先序遍历 1&#xff09;带头结点的单链表L&#xff0c;从首结点开始&#xff0c;依次两两比较&#xff0c;如果前者大于等于后者&#xff0c;说明是非递增的&#xff1b;否则递增。 2&#xff09; 1&#xff09;先遍历二叉树&#xff0c;…

【mars3d】基于vue3的marsgis通用UI库 mars-ui 的使用

一名脑残程序员的mars-ui心酸使用记录。 通过mars3d的官网我们可以看到&#xff0c;有配套的UI库使用&#xff0c;那么我们如何使用到自己的项目中呢&#xff0c;跟着文章一步一步来吧&#xff01; 1、引入UI库 ① 安装ant-design-vue cnpm install ant-design-vue --save②…

如何实现功能插件化

本文将介绍两种方式来实现功能插件化&#xff1a; Java SPISpring factories 在整个插件化的方案中&#xff0c;会涉及到如下 3 个组成部分&#xff1a; 插件定义&#xff08;即将插件定义为一个接口&#xff09; 插件实现&#xff08;即对插件接口的实现&#xff09; 这里…

【需求实现】输入多少就输出多少的拟合任务如何实现(二):进度条简化

文章目录 导读普通的输出方式上下求索TensorBoard是个不错的切入点与Callback参数对应的Callback方法官方的内置Callback官方进度条简单的猜测与简单的验证拼图凑齐了&#xff01; 导读 在训练模型的过程中往往会有日志一堆一堆的困扰。我并不想知道&#xff0c;因为最后我会在…

今天给大家分享几款好用的卸载神器

在日常使用电脑的过程中&#xff0c;我们经常需要安装和卸载各种软件。然而&#xff0c;有时候使用操作系统自带的卸载程序可能无法完全清除程序及其相关文件和注册表项&#xff0c;导致系统出现垃圾文件和残留问题。为了解决这个困扰&#xff0c;今天我将向大家分享几款好用的…

【Spring】基于注解方式存取JavaBean:Spring有几种注入方式?有什么区别?

前言 Hello&#xff0c;我是小黄。众所周知&#xff0c;Spring是一个开源的Java应用程序框架&#xff0c;其中包括许多通过注解实现依赖注入的功能。Spring提供了多种注入方式&#xff0c;可以满足不同的需求和场景。常见的注入方式包括构造函数注入、Setter方法注入和属性注入…

【Redis】Redis的高可用与持久化

文章目录 一、Redis 高可用1. 概念2. 高可用技术以及作用2.1 持久化2.2 主从复制2.3 哨兵2.4 集群 二、Redis 持久化1. 持久化的功能2. Redis 持久化方式 三、RDB 持久化1. 概述2. 触发条件2.1 手动触发2.2 自动触发2.3 其他自动发机制 3. 执行流程4. 启动时加载 四、AOF 持久化…

Modin 入门学习

Modin 是一个 Python 第三方库&#xff0c;用于加速 Pandas 的 API 执行速度。原始的 Pandas 是单线程执行的&#xff0c;而 Modin 则重新打包了 Pandas 里面的 API&#xff0c;使其同时在多个内核中运行&#xff0c;提高硬件性能的利用率。 使用方法很简单&#xff0c;安装 M…

2.9C++多态

C 继承扩展 C继承在实际开发中它可以帮助我们实现代码重用&#xff0c;减少代码冗余&#xff0c;提高代码的可维护性和可扩展性。 通过继承&#xff0c;我们可以从已有的类中派生出新的类&#xff0c;新的类可以继承父类的属性和方法&#xff0c;并且可以添加自己的属性和方法…

selenium元素定位---ElementClickInterceptedException(元素点击交互异常)解决方法

目录 前言&#xff1a; 1、异常原因 2、解决方法&#xff1a; 前言&#xff1a; 当使用Selenium进行元素定位和交互时&#xff0c;可能会遇到ElementClickInterceptedException&#xff08;元素点击交互异常&#xff09;的异常。这通常是由于页面上存在其他元素或弹出窗口遮…

ROS学习之基础包创建的详细流程:包括rosnode, rostopic, rosrun,roslaunch等使用

0 引言 本文旨在学习ROS基础包的从零开始创建&#xff0c;包括如何创建一个发布消息节点&#xff0c;一个接收消息节点&#xff0c;还有如何使用roslaunch同时启动多个节点&#xff0c;如何编译ROS工程包等操作。 默认已在Ubuntu系统中安装ROS机器人系统&#xff0c;比如Ubun…

AOP--拦截器

AOP应用--拦截器Spring拦截器拦截器执行流程前缀的添加统一异常处理统一数据返回格式返回String类型 AOP应用–拦截器 AOP的作用&#xff1a;统一功能处理&#xff1b;我们将以三个内容作为学习的掌握点&#xff1b;而这三点也是我们非常迫切需要的 1&#xff1a;用户登录权限…

Windows系统分区大小

Microsoft Reserved&#xff08;MSR&#xff09;——保留分区——16MB左右 EFI System Partition&#xff08;ESP&#xff09;——系统分区——100MB左右 Recovery Partition&#xff08;自起名字REP&#xff09;——恢复分区——450MB左右 其他分区——剩余

对rabbitmq进行压测

添加rabbitmq依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactI…