网关 Spring Cloud Gateway 简介 入门


💨 作者:laker,因为喜欢LOL滴神faker,又是NBA湖人队🏀(laker)粉丝儿(主要是老詹的粉丝儿),本人又姓,故取笔名:laker
❤️喜欢分享自己工作中遇到的问题和解决方案以及一些读书笔记和心得分享
🌰本人创建了微信公众号【Java大厂面试官】,用于和大家交流分享
🏰 个人微信【lakernote】,加作者备注下暗号:cv之道


简介

Spring Cloud Gateway 是Spring Cloud的一个全新的API网关项目,目的是为了替换掉Zuul1。Gateway可以与Spring Cloud Discovery Client(如Eureka)、Ribbon、Hystrix等组件配合使用,实现路由转发、负载均衡、熔断等功能,并且Gateway还内置了限流过滤器,实现了限流的功能。

Gateway基于Spring 5、Spring boot 2和Reactor构建,使用Netty作为运行时环境,比较完美的支持异步非阻塞编程。Netty使用非阻塞的IO,线程处理模型建立在主从Reactors多线程模型上。其中Boss Group轮询到新连接后与Client建立连接,生成NioSocketChannel,将channel绑定到Worker;Worker Group轮询并处理Read、Write事件。

微服务架下,服务之间容易形成网状的调用关系,这种网状的调用关系不便管理和维护,这种场景下API网关应运而生。作为后端服务的入口,API网关在微服务架构中尤其重要,在对外部系统提供API入口的要求下,API网关应具备路由转发、负载均衡、限流熔断、权限控制、轨迹追踪和实时监控等功能。

目前,很多微服务都基于的Spring Cloud生态构建。Spring Cloud生态为我们提供了两种API网关产品,分别是Netflix开源的Zuul1和Spring自己开发的Spring Cloud Gateway(下边简称为Gateway)。Spring Cloud以Finchley版本为分界线,Finchley版本发布之前使用Zuul1作为API网关,之后更推荐使用Gateway。

虽然Netflix已经在2018年5月开源了Zuul2,但是Spring Cloud已经推出了Gateway,并且在github上表示没有集成Zuul2的计划。所以从Spring Cloud发展的趋势来看,Gateway代替Zuul是必然的。

Spring Cloud Gateway 依赖 Spring Boot 和 Spring WebFlux,基于 Netty 运行。它不能在传统的 servlet 容器中工作,也不能构建成 war 包。

该工具提供了开箱即用的路由机制,经常在微服务应用程序中使用,作为将多个服务隐藏在单个外观后面的一种方式。

官方文档

SpringCloud Gateway 特征

SpringCloud官方,对SpringCloud Gateway 特征介绍如下:

  • 建立在Spring Framework 5,Project Reactor和Spring Boot 2.0之上

  • 能够匹配任何请求属性上的路由。

  • 谓词和过滤器特定于路由。

  • 断路器集成。

  • Spring Cloud DiscoveryClient集成

  • 易于编写的谓词和过滤器

  • 请求速率限制

  • 路径改写

从以上的特征来说,和Zuul的特征差别不大。SpringCloud Gateway和Zuul主要的区别,还是在底层的通信框架上。

在 Spring Cloud Gateway 中有如下几个核心概念需要我们了解:

(1)Route(路由):

Route 是网关的基础元素,由 ID、目标 URI、断言、过滤器组成。当请求到达网关时,由 Gateway Handler Mapping 通过断言进行路由匹配(Mapping),当断言为真时,匹配到路由。

(2)Predicate(断言):

Predicate 是 Java 8 中提供的一个函数。输入类型是 Spring Framework ServerWebExchange。它允许开发人员匹配来自 HTTP 的请求,例如请求头或者请求参数。简单来说它就是匹配条件。

(3)Filter(过滤器):

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

Spring Cloud Gateway 工作原理

Spring Cloud Gateway 的工作原理跟 Zuul 的差不多,最大的区别就是 Gateway 的 Filter 只有 prepost 两种。下面我们简单了解一下 Gateway 的工作原理图。

Spring Cloud Gateway工作原理

客户端向 Spring Cloud Gateway 发出请求,如果请求与网关程序定义的路由匹配,则该请求就会被发送到网关 Web 处理程序,此时处理程序运行特定的请求过滤器链。

过滤器之间用虚线分开的原因是过滤器可能会在发送代理请求的前后执行逻辑。所有 pre 过滤器逻辑先执行,然后执行代理请求;代理请求完成后,执行 post 过滤器逻辑。

路由配置

配置文件方式

spring:
  cloud:
    gateway:
      routes:
        - id: path_route
		  uri: https://www.baidu.com
          predicates:
            - Path=/spring_cloud

各字段含义如下:

  • id:我们自定义的路由 ID,保持唯一

  • uri:目标服务地址

  • predicates:路由条件,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。

当你访问 http://localhost:8080/spring_cloud 的时候就会转发到 https://www.baidu.com/spring_cloud。

代码方式

与上面配置文件方式效果一致

@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
    return builder.routes()
        .route(p -> p
            .path("/spring_cloud")
            .uri("https://www.baidu.com"))
            .id("myOtherID"))
            .build();
}

路由断言工厂

Spring Cloud Gateway使用Spring WebFlux HandlerMapping基础结构匹配路由。

它还包括许多内置的路由断言工厂。所有这些谓词都与HTTP请求的不同属性匹配。多个路由谓词工厂可以通过逻辑“和”进行组合。

路由匹配既可以通过编程方式应用,也可以通过配置属性文件使用其他类型的Route Predicate Factories来应用。

过滤器工厂

路由过滤器使修改传入的HTTP请求或传出的HTTP响应成为可能。

Spring Cloud Gateway包括许多内置的WebFilter工厂以及创建自定义过滤器的可能性。

注册中心相结合

Spring Cloud Gateway可以轻松地与服务发现和注册表库(例如Eureka Server和Consul)集成:

@Configuration
@EnableDiscoveryClient
public class GatewayDiscoveryConfiguration {
    @Bean
    public DiscoveryClientRouteDefinitionLocator 
      discoveryClientRouteLocator(DiscoveryClient discoveryClient) {
        return new DiscoveryClientRouteDefinitionLocator(discoveryClient);
    }
}

负载均衡

该LoadBalancerClientFilter寻找一个URI中使用的交换特性属性ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR。

如果URL具有lb方案(例如lb://baeldung-service),它将使用Spring Cloud LoadBalancerClient将名称*(即baeldung-service)*解析为实际的主机和端口。

未经修改的原始URL放置在ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR属性中。

监控

Spring Cloud Gateway利用Actuator API,这是一个著名的Spring-Boot库,它提供了一些现成的服务来监视应用程序。

一旦安装并配置了Actuator API,就可以通过访问/gateway/端点来可视化网关监视功能。

入门示例

现在,我们将使用路径断言创建一个简单的示例,将Spring Cloud Gateway用作代理服务器。

pom依赖

我们使用最新版本,构建方式可参考 如何正确选择Spring Boot与Spring Cloud的版本以及对应关系

这里我直接给出来pom.xml文件。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.1</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>demo</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
		<spring-cloud.version>2020.0.0</spring-cloud.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-gateway</artifactId>
		</dependency>
		<dependency>
    		<groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</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>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

代码

现在,我们在application.yml文件中创建一个简单的路由配置:

spring:
  cloud:
    gateway:
      routes:
        - id: laker
          uri: http://httpbin.org
          predicates:
            - Path=/get
management:
  endpoints:
    web:
      exposure:
        include: "*"

以及网关应用程序代码:

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

应用程序启动后,我们可以访问URL:http://localhost:8080/actuator/gateway/routes/laker以检查所有创建的路由配置:

{
	"predicate": "Paths: [/get], match trailing slash: true",
	"route_id": "laker",
	"filters": [],
	"uri": "http://httpbin.org:80",
	"order": 0
}

我们看到相对网址:/get被配置为路由, 因此点击网址http://localhost/get,我们将被重定向到http://httpbin.org:80

在这里插入图片描述

附录

反应式编程结合同步非阻塞IO或者异步非阻塞IO是目前网络编程框架的主流方向,最好要跟上主流的步伐掌握这些框架的使用,有能力最好成为它们的贡献者。

目前常见的反应式编程框架有:

  • ReactorRxJava2,其中Reactor在后端的JVM应用比较常见,RxJava2在安卓编写的APP客户端比较常见。
  • Reactor-Netty,这个是基于ReactorNetty封装的。
  • Spring-WebFluxSpring-Cloud-Gateway,其中Spring-Cloud-Gateway依赖Spring-WebFlux,而Spring-WebFlux底层依赖于Reactor-Netty

选用Spring-Cloud-Gateway不仅仅是为了使用新的技术,更重要的是它的性能有了不俗的提升,基准测试项目spring-cloud-gateway-bench的结果如下:

代理组件(Proxy)平均交互延迟(Avg Latency)平均每秒处理的请求数(Avg Requests/Sec)
Spring Cloud Gateway6.61ms32213.38
Linkered7.62ms28050.76
Zuul(1.x)12.56ms20800.13
None(直接调用)2.09ms116841.15

Spring Cloud 相关系列文章目录

网关服务

Spring Cloud Gateway


QQ群【837324215】
关注我的公众号【Java大厂面试官】,回复:常用工具资源等关键词(更多关键词,关注后注意提示信息)获取更多免费资料。

公众号也会持续输出高质量文章,和大家共同进步。

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lakernote

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值