微服务系列:服务网关 Spring Cloud Gateway 入门


Spring Cloud Gateway 是基于 Spring 5.0、Spring Boot 2.0 和 Project Reactor 等技术开发的网关。所以就有了前置知识 WebFlux 的学习,而学习 WebFlux 又需要 Stream 流和 Lambda 表达式等技术作为前置知识。

从这篇文章开始,将正式开始 微服务系列 的相关技术学习。

话不多说,开始今天的学习。

介绍

Spring Cloud Gateway

Spring Cloud Gateway是基于Spring生态系统之上构建的API网关,包括:Spring 5.xSpring Boot 2.xProject Reactor。它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。。

什么是服务网关

API Gateway(APIGW / API 网关),顾名思义,是系统对外的唯一入口。API网关封装了系统内部架构,为每个客户端提供定制的API。 近几年来移动应用与企业间互联需求的兴起。从以前单一的Web应用,扩展到多种使用场景,且每种使用场景对后台服务的要求都不尽相同。 这不仅增加了后台服务的响应量,还增加了后台服务的复杂性。随着微服务架构概念的提出,API网关成为了微服务架构的一个标配组件。

为什么要使用网关

微服务的应用可能部署在不同机房,不同地区,不同域名下。此时客户端(浏览器/手机/软件工具)想 要请求对应的服务,都需要知道机器的具体 IP 或者域名 URL,当微服务实例众多时,这是非常难以记忆的,对 于客户端来说也太复杂难以维护。此时就有了网关,客户端相关的请求直接发送到网关,由网关根据请求标识 解析判断出具体的微服务地址,再把请求转发到微服务实例。这其中的记忆功能就全部交由网关来操作了。

工作流程

image.png

客户端向 Spring Cloud Gateway 发出请求。如果 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。Handler 再通过指定的过滤器链(职责链设计模式)来将请求发送到我们实际的服务执行业务逻辑,然后返回。

特征

SpringCloud Gateway 特征如下:

  1. 基于 Spring Framework 5,Project Reactor 和 Spring Boot 2.0
  2. 集成 Hystrix 断路器
  3. 集成 Spring Cloud DiscoveryClient
  4. Predicates 和 Filters 作用于特定路由,易于编写的 Predicates 和 Filters
  5. 具备一些网关的高级功能:动态路由、限流、路径重写
  6. 路径重写
  7. 限流
  8. 动态路由

核心概念

  • 路由(Route):路由是网关最基础的部分,它由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配。
  • 断言(Predicate):Java8 中的断言函数。Spring Cloud Gateway 中的断言函数输入类型是 Spring 5.0 框架中 的 ServerWebExchange。Spring Cloud Gateway 中的断言函数允许开发者去定义匹配来自于 Http Request 中的任 何信息,比如请求头和参数等。
  • 过滤器(Filter):一个标准的 Spring Web Filter。Spring Cloud Gateway 中的 Filter 分为两种类型,分别是 Gateway Filter 和 Global Filter。过滤器将会对请求和响应进行处理。

上手使用

直接在 idea 中创建 Spring Boot 项目:

image.png

pom.xml 文件中自动引入 Spring Cloud Gateway 的依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
</dependencies>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

application.yml 配置文件:

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: cloud-gateway
          uri: http://192.168.1.211:8088/
          predicates:
            - Path=/ytb/**

各字段含义如下:

  • id:自定义的路由 ID,保持唯一
  • uri:目标服务地址
  • predicates:路由条件,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。
  • filters:过滤规则,这里没有用到。

上面这段配置的意思就是,配置了一个 id 为 cloud-gateway 的 URI 代理规则,路由的规则为:

当访问地址 http://localhost:8080/ytb/fileType/getFileTypeList 时,会自动转发到地址http://192.168.1.211:8088/ytb/fileType/getFileTypeList

转发到的地址是我的一个测试地址 返回如下:

image.png

除了 application.yml 配置之外呐,转发功能同样可以通过代码来实现,我们可以在启动类 GateWayApplication 中添加方法 customRouteLocator() 来定制转发规则。

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

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder){
        return builder.routes()
                .route("path_route", r -> r.path("/ytb/**").uri("http://192.168.1.211:8088/")).build();
    }
}

这里就用到了我们前置知识中的函数式编程。启动项目访问http://localhost:8080/ytb/fileType/getFileTypeList 地址,我们会得到与上面相同的返回结果。

路由规则

Spring Cloud Gateway 是通过 Spring WebFluxHandlerMapping 做为底层支持来匹配到转发路由,Spring Cloud Gateway 内置了很多 Predicates 工厂,这些 Predicates 工厂通过不同的 HTTP 请求参数来匹配,多个 Predicates 工厂可以组合使用。

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

下面就看看具体的路由规则吧。

Datetime

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

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

Cookie

匹配指定名称且其值与正则表达式匹配的cookie

spring: 
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: cloud-ytb
          uri: http://localhost:9201/
          predicates:
            - Cookie=username, ezhang

Header

匹配具有指定名称的请求头,\d+值匹配正则表达式

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

Host

匹配主机名的列表

spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: cloud-gateway
          uri: https://www.baidu.com
          predicates:
            - Host=**.baidu.com

使用 curl 测试,命令行输入:

curl http://localhost:8080 -H “Host: www.baidu.com”

image.png

Method

匹配请求methods的参数,它是一个或多个参数

spring: 
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: cloud-ytb
          uri: http://localhost:9201/
          predicates:
            - Method=GET,POST

Path

匹配请求路径

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

上面上手使用的就是用的匹配请求路径。

Query

匹配查询参数

spring: 
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: cloud-ytb
          uri: http://localhost:9201/
          predicates:
            - Query=username, ezhang.

RemoteAddr

匹配IP地址和子网掩码

spring: 
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: cloud-ytb
          uri: http://localhost:9201/
          predicates:
            - RemoteAddr=192.168.0.1

Weight

匹配权重

spring: 
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: cloud-ytb-v1
          uri: http://localhost:9201/
          predicates:
            - Weight=group1, 8
        - id: cloud-ytb-v2
          uri: http://localhost:9201/
          predicates:
            - Weight=group1, 2

在开发或者测试的时候,或者线上发布,线上服务多版本控制的时候,需要对服务提供权重路由,最常见的使用就是,一个服务有两个版本,旧版本V1,新版本v2。在线上灰度的时候,需要通过网关动态实时推送,路由权重信息。比如80%的流量走服务v1版本,20%的流量走服务v2版本。

路由配置

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

  • websocket配置方式
spring:
  cloud:
    gateway:
      routes:
        - id: cloud-ytb
          uri: ws://localhost:9213/
          predicates:
            - Path=/ytb/**
  • http地址配置方式
spring:
  cloud:
    gateway:
      routes:
        - id: cloud-ytb
          uri: http://localhost:9213/
          predicates:
            - Path=/ytb/**
  • 注册中心配置方式
    在 uri 的 schema 协议部分为自定义的 lb: 类型,表示从微服务注册中心(如 Nacos)订阅服务,并且进行服务的路由。
spring:
  cloud:
    gateway:
      routes:
        - id: cloud-ytb
          uri: lb://cloud-ytb
          predicates:
            - Path=/ytb/**

Spring Cloud Gateway 和 Zuul

spring-cloud-Gatewayspring-cloud的一个子项目。而zuul则是netflix公司的项目,只是spring将zuul集成在spring-cloud中使用而已。

因为zuul2.0连续跳票和zuul1的性能表现不是很理想,所以催生了spring团队开发了Gateway项目。

Spring Cloud Gateway 和 Zuul 两者的比较:

  • 两者均是web网关,处理的是http请求。
  • gateway对比zuul多依赖了spring-webflux,在spring的支持下,功能更强大,内部实现了限流、负载均衡等,扩展性也更强,但同时也限制了仅适合于Spring Cloud套件,而zuul则可以扩展至其他微服务框架中,其内部没有实现限流、负载均衡等。
  • gateway很好的支持异步,而zuul仅支持同步,那么理论上gateway则更适合于提高系统吞吐量(但不一定能有更好的性能),最终性能还需要通过严密的压测来决定。
  • 从框架设计的角度看,gateway具有更好的扩展性,并且其已经发布了2.0.0的 RELESE 版本,稳定性也是非常好的。

总的来说,在微服务架构,如果使用了Spring Cloud生态的基础组件,则Spring Cloud Gateway相比而言更加具备优势,单从流式编程+支持异步上就足以让开发者选择它了。

对于小型微服务架构或是复杂架构(不仅包括微服务应用还有其他非Spring Cloud服务节点),zuul也是一个不错的选择。

注意:

Spring Cloud Gateway 需要 SpringBootSpringWebFlux提供的 Netty 运行,不能打成 war 包放在 Tomcat 中运行,因此在项目当中也没有必要添加 spring-boot-starter-web 依赖。

官网:Spring Cloud Gateway

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值