文章目录

  • Spring Cloud(10)——新一代网关Spring Cloud Gateway
    • 1、背景知识——API网关
    • 2、Spring Cloud Gateway 详细概述
    • 3、Spring Cloud Gateway 入门配置
      • 3.1、环境搭建
      • 3.2、Spring Cloud Gateway 配置路由的两种方式
    • 4、配置动态路由
    • 5、Predicate的使用
    • 6、Filter的使用
      • 6.1、过滤器工厂
      • 6.3、自定义全局过滤器

Spring Cloud(10)——新一代网关Spring Cloud Gateway

在Spring Cloud(09)——Hystrix断路器中,实现了分布式场景下服务发生故障时,服务的熔断和降级。现在我们用新一代网关Gateway来保护、增强和控制对于 API 服务的访问。

1、背景知识——API网关

网关的角色是作为一个 API 架构,用来保护、增强和控制对于 API 服务的访问。

API 网关是一个处于应用程序或服务(提供 REST API 接口服务)之前的系统,用来管理授权、访问控制和流量限制等,这样 REST API 接口服务就被 API 网关保护起来,对所有的调用者透明。因此,隐藏在 API 网关后面的业务系统就可以专注于创建和管理服务,而不用去处理这些策略性的基础设施。

2、Spring Cloud Gateway 详细概述

1、什么是Gateway

  • Spring Cloud Gateway是Spring官方基于Spring 5.0,Spring Boot 2.0和Project Reactor等技术开发的网关,Spring Cloud Gateway旨在为微服务架构提供一种简单而有效的统一的API路由管理方式。

  • Spring Cloud Gateway 作为 Spring Cloud 生态系中的网关,其目标是替代 Netflix Zuul,在Spring Cloud 2.0以上版本中,没有对新版本的Zuul 2.0以上最新性能版本进行集成,仍然还是使用的Zuul 1.x非Reactor模式的老版本。而为了提升网关的性能,Spring Cloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty

  • Spring Cloud Gateway提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全、监控/指标和限流等。

2、Gateway作用:

  • 反向代理
  • 鉴权
  • 流量控制
  • 熔断
  • 日志监控
  • 。。。。。。

3、微服务架构中网关的位置:

4、Spring Cloud Gateway具有如下特性:

  • 基于Spring 5.0,Spring Boot 2.0和Project Reacto进行构建
  • 动态路由:能够匹配任何请求属性
  • 可以对路由指定Predicate(断言)和Filter(过滤器),并易于编写
  • 集成Hystrix的断路器功能
  • 集成Spring Cloud 服务发现功能
  • 请求限流功能
  • 支持路径重写

5、Spring Cloud Gateway 与Zull的区别:

  • 在Spring Cloud Finchley 正式版之前,Spring Cloud 推荐使用的网关是 Netflix 提供的Zuul
  • Zuul 1.x 是一个基于阻塞I / O 的API Gateway(API 网关)
  • Zuul1.x 基于Servlet 2.5使用阻塞架构,它不支持任何长连接(如WecSocket)Zuul 的设计模式和Nginx较像,每次I / O操作都是从工作线程中选择一个执行,请求线程被阻塞到工作线程完成,但是差别是Nginx用C++ 实现,Zull用 Java实现,而JVM 本身会有第一次加载较慢的情况,使得Zuul 的性能相对较差。
  • Zuul2.x 理念更先进,像基于Netty非阻塞和支持长连接,但SpringCloud 目前还没有整合。Zuul2.x 的性能较Zuul1.x 有较大的提升。在性能方面,根据官方提供的基准测试, Spring Cloud Gateway的 RPS(每秒请求数)是Zuul的1.6倍。
  • Spring Cloud Gateway 建立在 Spring 5.0,Spring Boot 2.0和 Project Reactor之上,使用非阻塞 API。
  • Spring Cloud Gateway 还支持 WebSocket,并且与Spring 紧密集成拥有更好的开发体验。

SpringCloud Gateway和Zuul主要的区别,是在底层的通信框架上。

Zuul使用的是Servlet 2.5阻塞架构,SpringCloud Gateway使用的是Webflux,Webflux是基于Servlet3.1的异步非阻塞框架。

6、Spring Cloud Gateway 三大核心概念:

  • Filter(过滤器):

和Zuul的过滤器在概念上类似,可以使用它拦截和修改请求,并且对上游的响应,进行二次处理。过滤器为org.springframework.cloud.gateway.filter.GatewayFilter类的实例。

  • Route(路由):

网关配置的基本组成模块,和Zuul的路由配置模块类似。一个Route模块由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配,目标URI会被访问。

  • Predicate(断言):

这是一个 Java 8 的 Predicate,可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。断言的输入类型是一个 ServerWebExchange。

7、Gateway工作流程:

工作流程图如下

客户端向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。

Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。

Filter在 “pre” 类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,

在“post” 类型的过滤器中可以做响应内容、响应头修改、日志的输出、流量监控等,有着非常重要的作用。

核心逻辑:路由转发 + 执行过滤器链

Zuul官网:https://github.com/netflix/zuul/tree/1.x

Gateway官网:https://spring.io/projects/spring-cloud-gateway

3、Spring Cloud Gateway 入门配置

3.1、环境搭建

1、创建cloud -gateway-gateway9527模块

2、导入pom依赖

<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>com.cheng.springcloud</groupId><artifactId>cloud-api-commons</artifactId><version>${project.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>
</dependencies>

3、编写yml配置文件

server:port: 9527spring:application:name: cloud-gatewayeureka:instance:hostname: cloud-gateway-serviceclient:service-url:register-with-eureka: truefetch-registry: truedefaultZone: http://eureka7001.com:7001/eureka

4、创建主启动类

@SpringBootApplication
@EnableEurekaClient
public class GatewayMain9527 {public static void main(String[] args) {SpringApplication.run(GatewayMain9527.class,args);}
}

配置cloud-provider-payment8001服务提供者模块

用8001模块中下面两个方法进行测试:

@GetMapping(value = "/payment/get/{id}")
public CommonResult getPaymentById(@PathVariable("id") Long id){Payment payment = paymentService.getPaymentById(id);log.info("=======查询结果="+payment);if (payment != null){return new CommonResult(200,"查询执行成功,serverPort="+serverPort,payment);}else {return new CommonResult(500,"查询id为"+id+"执行失败",null);}
}@GetMapping(value = "/payment/lb")
public String getPaymentLb(){return serverPort;
}

之前我们8001的服务接口都是对外暴露的,现在我们想在8001外面套一层gateway9527:

在8001的yml配置文件中增加配置:

server:port: 9527spring:application:name: cloud-gatewaycloud:gateway:routes:- id: payment_routh  #路由的id,没有固定规则但要求唯一,建议配合服务名uri: http://localhost:8001   #匹配后提供服务的路由地址predicates:- Path=/payment/get/**    #断言,路径向匹配的进行路由- id: payment_routh2uri: http://localhost:8001predicates:- Path=/payment/lb/**eureka:instance:hostname: cloud-gateway-serviceclient:service-url:register-with-eureka: truefetch-registry: truedefaultZone: http://eureka7001.com:7001/eureka

测试:

  1. 启动cloud-eureka-server7001和cloud-eureka-server7002模块
  2. 启动cloud-provider-payment8001模块
  3. 启动cloud -gateway-gateway9527网关模块

添加网关前的访问:http://localhost:8001/payment/get/2 和 http://localhost:8001/payment/lb

添加网关后的访问:http://localhost:9527/payment/get/2 和 http://localhost:9527/payment/lb

只要符合路由转发规则,网关9527可以成功的访问到8001模块提供的服务:

3.2、Spring Cloud Gateway 配置路由的两种方式

1、第一种:yml配置的方式,见前面步骤

2、第二种:编码的方式,代码中注入RouteLocator的Bean

业务需求:用编码的方式,通过9527网关访问到外网的百度新闻的地址 https://news.baidu.com/guonei

package com.cheng.springcloud.config;import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Configuration;@Configuration
public class GatewayConfig {@Beanpublic RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();routes.route("path_route_baidu",r -> r.path("/guonei").uri("https://news.baidu.com/guonei")).build();return routes.build();}
}

上面的配置类中,配置了一个id为path_route_baidu 的路由规则,

当请求:http://localhost:9527/guonei 时会自动跳转到 https://news.baidu.com/guonei

4、配置动态路由

默认情况下Gateway会根据注册中心的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能。

修改9527网关模块的yml位置文件:

server:port: 9527spring:application:name: cloud-gatewaycloud:gateway:discovery:locator:enabled: true  #开启从注册中心动态创建路由的功能,利用微服务名配置动态路由routes:- id: payment_routh  #路由的id,没有固定规则但要求唯一,建议配合服务名
#          uri: http://localhost:8001   #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配路由后提供服务的路由地址  url的协议是lb,表示启用Gateway的负载均衡的功能predicates:- Path=/payment/get/**    #断言,路径向匹配的进行路由- id: payment_routh2#uri: http://localhost:8001uri: lb://cloud-payment-service #匹配路由后提供服务的路由地址predicates:- Path=/payment/lb/**eureka:instance:hostname: cloud-gateway-serviceclient:service-url:register-with-eureka: truefetch-registry: truedefaultZone: http://eureka7001.com:7001/eureka

开启cloud-provider-payment8001和cloud-provider-payment8002模块进行测试:

访问请求:http://localhost:9527/payment/lb

第一次访问:

第二次访问:

不断实现了动态路由转发,还实现了轮询的负载均衡策略。

5、Predicate的使用

Predicate 来源于 Java 8,是 Java 8 中引入的一个函数,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。可以用于接口请求参数校验、判断新老数据是否有变化需要进行更新操作。

在 Spring Cloud Gateway 中 Spring 利用 Predicate 的特性实现了各种路由匹配规则,有通过 Header、请求参数等不同的条件来进行作为条件匹配到对应的路由。网上有一张图总结了 Spring Cloud 内置的几种 Predicate 的实现。

After Route Predicate Factory

匹配在指定日期时间之后发生的请求:

先获得当前时间:

ZonedDateTime now = ZonedDateTime.now();
System.out.println(now);//2021-07-15T13:08:05.637+08:00[Asia/Shanghai]

断言条件:

          predicates:- Path=/payment/lb/**- After=2021-07-15T14:08:05.637+08:00[Asia/Shanghai]

访问请求:http://localhost:9527/payment/lb

再访问一次:

我们把时间往后推迟一个小时,再访问一次:报404异常

Between Route Predicate Factory

匹配发生在datetime1之后和datetime2之前的请求。datetime2参数必须在datetime1之后。

predicates:- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]

Cookie Route Predicate Factory

接受两个参数,Cookie名称和一个正则表达式)。路由规则会通过获取对应的Cookie名称和正则表达式去匹配,如果匹配就会执行路由,如果没有匹配则不执行。

断言条件:

predicates:- Path=/payment/lb/**- Cookie=username,wpc  #键值对

使用curl发送请求进行测试:curl 是常用的命令行工具,用来请求 Web 服务器。

curl详细介绍: http://www.ruanyifeng.com/blog/2019/09/curl-reference.html

不带cookie请求时:报404异常

带cookie请求时:成功访问

Header Route Predicate Factory

Header Route Predicate 和 Cookie Route Predicate 一样,也是接收 2 个参数,一个 header 中属性名称和一个正则表达式,这个属性值和正则表达式匹配则执行。

断言条件:

predicates:- Path=/payment/lb/**- Header=X-Request-Id, \d+  #请求头要有X-Request-Id属性并且值为整数的正则表达式

使用 curl 测试,命令行输入: curl http://localhost:9527/payment/lb -H “X-Request-Id:88”

Host Route Predicate Factory

Host Route Predicate 接收一组参数,一组匹配的域名列表,这个模板是一个 ant 分隔的模板,用.号作为分隔符。它通过参数中的主机地址作为匹配规则。

断言条件:

          predicates:- Path=/payment/lb/**- Host=**.baidu.com

使用 curl 测试,命令行输入: curl http://localhost:9527/payment/lb -H “Host: www.baidu.com”

Method Route Predicate Factory

可以通过是 POST、GET、PUT、DELETE 等不同的请求方式来进行路由。

断言条件:

          predicates:- Path=/payment/lb/**- Method=GET

使用 curl 测试,命令行输入: curl http://localhost:9527/payment/lb (curl 默认是以 GET 的方式去请求)

我们再以 POST 的方式请求测试:curl -X POST http://localhost:9527/payment/lb 返回 404 没有找到,证明没有匹配上路由

Query Route Predicate Factory

Query Route Predicate 支持传入两个参数,一个是属性名一个为属性值,属性值可以是正则表达式。

断言条件:

          predicates:- Path=/payment/lb/**- Query=keep, wei. #当请求中包含keep属性并且参数值是以wei开头的长度为4位的字符串才会进行匹配和路由。

使用 curl 测试,命令行输入: curl localhost:9527/payment/lb?keep=weip

RemoteAddr Route Predicate Factory

Predicate 也支持通过设置某个 ip 区间号段的请求才会路由,RemoteAddr Route Predicate 接受 cidr 符号(IPv4 或 IPv6 )字符串的列表(最小大小为1),例如 192.168.0.1/16 (其中 192.168.0.1 是 IP 地址,16 是子网掩码)。

断言条件:

          predicates:- Path=/payment/lb/**- Query=keep, wei. #当请求中包含keep属性并且参数值是以wei开头的长度为4位的字符串才会进行匹配和路由。

如果请求的远程地址是 192.168.1.10,则此路由将匹配。

6、Filter的使用

6.1、过滤器工厂

GatewayFilter Factory 是 Spring Cloud Gateway 中提供的过滤器工厂。Spring Cloud Gateway 的路由过滤器允许以某种方式修改传入的 HTTP 请求或输出的 HTTP 响应,只作用于特定的路由。

Spring Cloud Gateway 中内置了很多过滤器工厂,直接采用配置的方式使用即可,同时也支持自定义 GatewayFilter Factory 来实现更复杂的业务需求。

1、AddRequestHeader 过滤器工厂

通过名称我们可以快速明白这个过滤器工厂的作用是添加请求头。

符合规则匹配成功的请求,将添加 X-Request-Foo:bar 请求头,将其传递到后端服务中,后方服务可以直接获取请求头信息。

2、RemoveRequestHeader 过滤器工、

RemoveRequestHeader 是移除请求头的过滤器工厂,可以在请求转发到后端服务之前进行 Header 的移除操作。

spring:cloud:gateway:routes:- id: removerequestheader_routeuri: http://c.biancheng.net- RemoveRequestHeader=X-Request-Foo

3、SetStatus 过滤器工厂

SetStatus 过滤器工厂接收单个状态,用于设置 Http 请求的响应码。它必须是有效的 Spring Httpstatus(org.springframework.http.HttpStatus)。它可以是整数值 404 或枚举类型 NOT_FOUND。

spring:cloud:gateway:routes:- id: setstatusint_routeuri: http://c.biancheng.netfilters:- SetStatus=401

4、RedirectTo过滤器工厂

RedirectTo 过滤器工厂用于重定向操作,比如我们需要重定向到百度。

spring:cloud:gateway:routes:- id: prefixpath_routeuri: http://c.biancheng.netfilters:- RedirectTo=302, http://baidu.com

5、PrefixPath过滤器工厂

对所有的请求路径添加前缀:

spring:cloud:gateway:routes:- id: prefixpath_routeuri: https://example.orgfilters:- PrefixPath=/mypath

访问/hello的请求被发送到https://example.org/mypath/hello。

6.3、自定义全局过滤器

全局过滤器作用于所有的路由,不需要单独配置,我们可以用它来实现很多统一化处理的业务需求,比如权限认证、IP 访问限制等。

定义MyLogGatewayFilter类,实现GlobalFilter, Ordered 接口

package com.cheng.springcloud.filter;import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;@Component
@Slf4j
public class MyLogGatewayFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {String username = exchange.getRequest().getQueryParams().getFirst("username");if (username == null){log.info("=======用户名为null=======,非法用户");exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);return exchange.getResponse().setComplete();}return chain.filter(exchange); //请求放行}@Overridepublic int getOrder() {return 0;}
}

访问请求: http://localhost:9527/payment/lb?username=dfds

如果不设置username的参数, http://localhost:9527/payment/lb 控制台提示错误信息

Spring Cloud(10)——新一代网关Spring Cloud Gateway相关推荐

  1. Spring Cloud学习笔记—网关Spring Cloud Gateway官网教程实操练习

    Spring Cloud学习笔记-网关Spring Cloud Gateway官网教程实操练习 1.Spring Cloud Gateway介绍 2.在Spring Tool Suite4或者IDEA ...

  2. spring cloud gateway 网关_微服务网关Spring Cloud Gateway全搞定

    一.微服务网关Spring Cloud Gateway 1.1 导引 文中内容包含:微服务网关限流10万QPS.跨域.过滤器.令牌桶算法. 在构建微服务系统中,必不可少的技术就是网关了,从早期的Zuu ...

  3. 第五章 微服务网关Spring Cloud Gateway

    5.1 微服务网关简介 第三章我们介绍了通过Spring Cloud LoadBalancer实现了微服务之间的调⽤和负载均衡,以及使⽤Spring Cloud OpenFeign声明式调⽤,那我们的 ...

  4. Spring Cloud(六) 服务网关GateWay 入门

    前文回顾: Spring Cloud(一)Eureka Server-单体及集群搭建 Spring Cloud(二) 配置Eureka Client Spring Cloud(三) 熔断器Hystri ...

  5. 网关 Spring Cloud Gateway

    一. Gateway 简介 Spring Cloud Gateway 是Spring Cloud团队的一个全新项目,基于Spring 5.0.SpringBoot2.0.Project Reactor ...

  6. 网关Spring Cloud Gateway的配置和使用

    文章目录 1. 什么是Spring Cloud Gateway? 2. Gateway与zuul的区别 3. Gateway的配置和使用 ①:常用的路由断言工厂 ②:常用的过滤器工厂(GatewayF ...

  7. 客快物流大数据项目(一百一十七):网关 Spring Cloud Gateway

    文章目录 网关 Spring Cloud Gateway 一.简介 1.功能特性

  8. Spring Cloud 微服务网关Gateway组件

    一.网关介绍 大家都知道在微服务架构中,一个系统会被拆分为多个微服务,那么作为客户端如何去调用这么多的微服务呢?如果没有网关的存在,我们只能在客户端记录每个微服务的地址,然后分别去用. 这样的架构会存 ...

  9. 微服务网关终结者?Spring Cloud推出新成员Spring Cloud Gateway

    导语:Spring Cloud Gateway基于Spring Boot 2,该项目提供了一个构建在Spring 生态之上的 API 网关.Spring Cloud Gateway旨在提供一种简单而有 ...

最新文章

  1. ggplot2:9绘图需要的数据整理技术-数据转换
  2. matlab函数isempty_matlab基本函数inf, isempty, round, floor, fix
  3. iOS手势识别的详细使用(拖动,缩放,旋转,点击,手势依赖,自定义手势)
  4. vue 动态生成路由菜单(从后端请求到菜单数据,生成左侧菜单栏)
  5. Zarafa 7.0.11/7.1.2 发布
  6. 一位老司机谈谈掏心窝子的话
  7. 未来脑机接口的电极”衣服”可能长这样,你会喜欢吗?
  8. Unity3D绑定button监听事件
  9. MongoDB入门学习(二):MongoDB的基本概念和数据类型
  10. HTML实现跳转到页面指定位置
  11. 多层图,dj+dp Gym 102501A Environment-Friendly
  12. python展开 c函数中的宏预处理_C 语言常用的预处理-宏函数
  13. 终于等到放学了的飞鸽传书
  14. 如何不用鼠标操作电脑
  15. hibernate5(8)操纵对象入门[3]操控对象封装方法
  16. 3D渲染和动画制作KeyShot Pro for mac
  17. nginx 安全优化
  18. php是什么电器元件,第三代计算机采用的主要电子元器件是什么
  19. 树上启发式合并算法概述及习题
  20. OLAP工具在企业决策支持系统中的应用

热门文章

  1. Linux卸载百度输入法失败,ubuntu20.04安装百度输入法,亲测有效!
  2. 如何实现Windowns释放20%的网速
  3. 从原理到操作,让你在 APISIX 中代理 Dubbo 服务更便捷
  4. python画图(标记、marker、设置标记大小、marker符号大全)(图文详细入门教程五)
  5. 如何选用模块化UPS
  6. 开源 | 携程 Foxpage 前端低代码框架
  7. 西门子V20变频器modbus rtu通信调试
  8. OpenGL 图形变换练习(平移,缩小)——画小汽车
  9. 史上最全!中国电信5G 2B专网介绍来了
  10. Python txt文件转成xlsx文件