spring cloud 之 gateway

网关介绍

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

现有网关介绍

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;
    }
}


 

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

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

相关文章

高性能消息中间件 RabbitMQ

一、RabbitMQ概念 1.1 MQ是什么 消息队列 MQ全称Message Queue&#xff08;消息队列&#xff09;&#xff0c;是在消息的传输过程中保存消息的容器。多用于系统之间的异步通信。 同步通信相当于两个人当面对话&#xff0c;你一言我一语。必须及时回复&#xff1a; 异步通信相…

基于Arduino UNO的循迹小车

目录 1.analogWrite函数的使用 2.红外循迹模块介绍 3.循迹小车代码实现 4.实物示例 1.analogWrite函数的使用 用analogWrite来替换digitalWrite 说明 将一个模拟数值写进Arduino引脚。这个操作可以用来控制LED的亮度, 或者控制电机的转速. 在Arduino UNO控制器中&#…

查询Oracle当前用户下,所有数据表的总条数

需求&#xff1a;查询Oracle当前用户下&#xff0c;所有数据表的总条数 方法&#xff1a;存储过程 右键点击Procedures&#xff0c;点击New 点击OK 把存储过程写进去&#xff0c;然后点击编译运行&#xff1a; create or replace procedure tables_count ist_count numbe…

xshell安装jdk1.8环境

xshell安装jdk1.8环境 大家好&#xff0c;今天我们来学习一下xshell安装jdk1.8环境&#xff0c;好好看&#xff0c;好好学&#xff0c;超详细的 第一步 进入xshell官网下载 第二步 打开xshell新建一个会话&#xff0c;如下图&#xff1a; 第三步 输入你的名称、主机ip、端口号(…

CSS中伪类详解和用法例子详解

文章目录 一、伪类介绍二、伪类选择器1.动态伪类2.结构伪类3.否定伪类4.状态伪类5.目标伪类 一、伪类介绍 用于已有元素处于某种状态时&#xff08;滑动、点击等&#xff09;为其添加对应的样式&#xff0c;这个状态是根据用户行为而动态变化的。 二、伪类选择器 动态伪类作…

Arduino uno 环境配置 for Mac

1、IDE 在官网下载 官网地址&#xff1a;https://www.arduino.cc/en/software 看到钱&#x1f4b0;不要怕&#xff0c;只是问你捐不捐款&#xff0c;不收钱&#xff0c;你直接安装就行 &#xff08;你也可以捐一点&#xff5e;&#xff09; 安装之后 2、安装驱动 地址 &…

互联网+洗鞋店预约小程序新模式;

互联网洗鞋店预约小程序 1、线上线下业务的结合。 传统的线下业务消费者到店可以向其推介线上的预约到家服务&#xff0c;让线下的消费者成为小程序内的会员&#xff0c;留存客户之后线上可直接触达&#xff0c;减少与消费者的距离&#xff0c;从等待客户到可以主动出击&…

黑客是什么?想成为黑客需要学习什么?

什么是黑客 在《黑客辞典》里有不少关于“黑客”的定义, 大多和“精于技术”或“乐于解决问题并超越极限”之类的形容相关。然而&#xff0c;若你想知道如何成为一名黑客&#xff0c;只要牢记两点即可。 这是一个社区和一种共享文化&#xff0c;可追溯到那群数十年前使…

6.Mysql主从复制

文章目录 Mysql主从复制读写分离概念&#xff1a;读写分离的作用&#xff1a;读写分离的作用条件&#xff1a;主从复制与读写分离mysq支持的复制类型主从复制的工作过程配置时间同步主服务器配置从服务器配置 读写分离MySQL 读写分离原理目前较为常见的 MySQL 读写分离分为以下…

A核与M核异构通信过程解析

现在越来越多的产品具有M core和A core的异构架构&#xff0c;既能达到M核的实时要求&#xff0c;又能满足A核的生态和算力。比如NXP的i.MX8系列、瑞萨的RZ/G2L系列以及TI的AM62x系列等等。虽然这些处理器的品牌及性能有所不同&#xff0c;但多核通信原理基本一致&#xff0c;都…

Linux - 那些年测试服务器带宽的 3 种方式

方式一 speedtest-cli wget -O speedtest-cli https://raw.githubusercontent.com/sivel/speedtest-cli/master/speedtest.pychmod x speedtest-cliorcurl -Lo speedtest-cli https://raw.githubusercontent.com/sivel/speedtest-cli/master/speedtest.pychmod x speedtest-c…

重生之我测阿里云U1实例(通用算力型实例)

官方福利&#xff01;&#xff01;&#xff01;&#xff01;大厂羊毛你确定不薅&#xff1f;&#xff1f;&#xff1f; 参与ECSU实例评测&#xff0c;申请免费体验机会&#xff1a;https://developer.aliyun.com/mission/review/ecsu 参与ECSU实例评测&#xff0c;申请免费体验…

一些零散的查询知识

一、all any some 表&#xff1a; all大于所有的值&#xff1a; any some:大于任意一个即可 例题&#xff1a; 大于50部门所有员工工资的人&#xff1a; 等价于&#xff1a; 二、exists关键字 1、exists查询 exists(子查询) 如果有满足条件的记录&#xff0c;那么exi…

C/C++内存管理(内存分布、动态内存分配、动态内存分配与释放、内存泄漏等)

喵~ 内存之5大区&#xff08;栈区、堆区、静态区、常量区、代码区&#xff09;C/C中各自的内存分配操作符内存泄露?内存泄漏检测方法 内存之5大区&#xff08;栈区、堆区、静态区、常量区、代码区&#xff09; 1、栈区&#xff08;stack&#xff09;&#xff1a;由编译器自动分…

【从删库到跑路】详细讲解MySQL的函数和约束作用

&#x1f38a;专栏【MySQL】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【如愿】 大一同学小吉&#xff0c;欢迎并且感谢大家指出我的问题&#x1f970; 文章目录 &#x1f354;函数⭐字符串函数&#x1f388;字符串拼接函数&…

LabVIEW开发呼吸分析系统

LabVIEW开发呼吸分析系统 在日常生活中&#xff0c;许多人都在练习调息法&#xff0c;但大多数人都不知道如何以完美的方式做。不当的做法不会带来适当的结果。一种使用LabVIEW分析呼吸信号的方法&#xff0c;以使人们以完美的方式练习调息。这有助于从业者按照系统指定的说明…

Vue2封装一个全局通知组件并发布到NPM

✍&#x1f3fc;作者&#xff1a;周棋洛&#xff0c;计算机学生 ♉星座&#xff1a;金牛座 &#x1f3e0;主页&#xff1a;点击查看更多 &#x1f310;关键&#xff1a;vue2 组件封装 npm发包 文章目录 1. 前言 &#x1f343;2. 我为什么要封装通知插件 ❓3. 初始化vue空项目 &…

Learn Mongodb DB数据库部署 ②

作者 : SYFStrive 博客首页 : HomePage &#x1f4dc;&#xff1a; PHP MYSQL &#x1f4cc;&#xff1a;个人社区&#xff08;欢迎大佬们加入&#xff09; &#x1f449;&#xff1a;社区链接&#x1f517; &#x1f4cc;&#xff1a;觉得文章不错可以点点关注 &#x1f44…

【STM32】软件I2C控制频率

在上一篇文章中&#xff0c;我们已经介绍了整个软件I2C的实现原理&#xff0c;但是也遗留了一个问题&#xff0c;那就是I2C速率的控制&#xff0c;其实就是控制SCL信号的频率。 微秒级延时 在上篇文章中&#xff0c;我们使用了SysTick进行延时&#xff0c;具体如下&#xff1…

Ubuntu下编译VTK

1.先安装QT&#xff0c;不知道不装行不行&#xff0c;我们项目需要。 2.去VTK官网下载VTK源码。 3.解压源码。 4.编译需要用cmake-gui&#xff0c;装QT的一般都有&#xff0c;但需要把路径添加到PATH才能用。 5.打开cmake-gui&#xff0c;设置源码路径&#xff0c;编译输出路…