1、概述简介
在Spring Cloud 1.x
中,网关使用的是Zuul 1
,在Spring Cloud 2.x
中,网关使用的是Gateway
,因为Zuul 2
版本进展缓慢,所以Spring Cloud
自己研发了网关,Gateway
是原Zuul 1
的替代版。Gateway采用异步非阻塞模型开发,性能上不需要担心
,虽然Netflix发布了Zuul 2版本,但是Spring Cloud并没有整合的计划,所以才自己推出了Gateway的方案。
Spring Cloud Gateway
是Spring Cloud
的一个全新项目,基于Spring 5+Spring Boot 2.x+Project Reactor等技术开发的网关,旨在为微服务架构提供一种简单有效的统一API路由管理方式
。
Spring Cloud Gateway
作为Spring Cloud
生态系统中的网关,目标是替代Zuul 1
,在Spring Cloud 2.x
版本中,没有对新版本Zuul 2
最新高性能版本进行集成,仍然使用的Zuul 1非Reactor模式的老版本
,为了提升网关性能,Spring Cloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层使用了高性能的Reactor模式通信框架Netty
。
Spring Cloud Gateway
目标是提供统一的路由方式
,并且基于Filter
链方式提供网关基本功能:安全
、监控
、指标
、限流
。
Spring Cloud Gateway
网关的作用:反向代理
、鉴权
、流量控制
、熔断
、日志监控
等。
在微服务架构中,网关的位置,位于各个微服务的上一层,通过网关后,就访问到了具体的微服务了
。
Spring Cloud Gateway
特性:
- 基于
Spring Framework 5
+Project Reactor
+Spring Boot 2.x
进行构建 - 动态路由:能够匹配任何请求属性
- 支持路由指定
Predicate(断言
)和Filter(过滤器)
,而且编写容易 - 集成了
Hystrix
断路器功能 - 集成
Spring Cloud服务发现
功能 - 支持请求限流功能
- 支持路径重写功能
Spring Cloud Gateway
和Zuul
的区别:
在Spring Cloud Finchley
正式版之前,Spring Cloud
推荐的网关是Netflix
提供的Zuul
;
Zuul 1
采用的是阻塞I/O
的API网关Zuul 1
使用Servlet2.5的阻塞架构实现
,不支持任何长连接(如WebSocket)
,Zuul
的设计模式和Nginx比较像
,每次I/O
都从工作线程中选择一个执行,请求线程在工作线程完成之前一直是阻塞的,Nginx是C++实现
,Zuul是Java实现
,JVM
在第一次的加载时候,会比较慢,所以Zuul的性能比较差
Zuul 2
设计理念跟先进,基于Netty非阻塞和支持长连接
,但是目前Spring Cloud没有整合它
,Zuul 2
的性能比Zuul 1
性能有较大提升,Spring Cloud Gateway的性能也不错
,官方测试数据表示,Spring Cloud Gateway的RPS(每秒请求数)是Zuul 1的1.6倍
Spring Cloud Gateway
建立在Spring Framework 5 + Project Reactor + Spring Boot 2.x
之上,使用非阻塞API
Spring Cloud Gateway还支持WebSocket
,与Spring
紧密集成拥有更好的开发体验
Zuul 1
模型缺点:Zuul 1采用传统Servlet I/O处理模型
,但请求进入servle
t容器时,servlet
容器会为其绑定一个线程,在并发不高的情况下是适用的,当并发量增加,线程数就会增加,但是线程资源是非常昂贵的(线程上下文切换内存消耗大),会影响到请求处理时间。有些简单的业务场景,并不需要每个请求分配一个线程,简单业务的高并发下,实际可能只需要几个线程就能扛得住,因此,每个请求分配一个线程,在高并发环境下并没有优势。
Gateway
模型:Gateway模型采用的是WebFlux框架
,这个框架是一个典型的非阻塞异步的框架
,并且在Servlet 3.1后,支持了异步非阻塞
,框架的核心是基于Reactor相关API实现的
。相对于传统Web框架,它可以运行在支持Servlet 3.1容器上的组件中(如Netty
、Undertow
等)。Spring WebFlux
是Spring 5
引入的新的响应式框架,区别于Spring MVC
,不需要依赖Servlet API
,完全异步非阻塞,并且基于Reactor来实现响应式流规范。
2、三大核心概念
2-1、Route(路由)
路由是构建网关的基本模块,由ID
,目标URI
一系列断言和过滤器组成,如果断言为true
,则匹配该路由。
2-2、Predicate(断言)
参考Java8
的java.util.function.Predicate
,开发人员可以匹配HTTP
请求中的所有内容(比如请求头,请求参数等),如果请求与断言匹配,则进行路由
。
2-3、Filter(过滤)
类似于Web
开发中的过滤器,这里指的是Spring
框架中GatewayFilter实例
,使用过滤器可以在请求被路由之前或之后对请求进行修改
。
总结:
路由
的功能是由断言和过滤组合来实现的
,一个Web
请求发送后,先经过网关,网关里的断言和过滤用来判断这个请求是否需要路由转发,当断言为true,过滤器放行时候,这个请求进行路由转发,此时,请求才到达具体的微服务模块。
3、Gateway工作流程
客户端向Spring Cloud Gateway
发送请求,然后在Gateway Handler Mapping
中找到与请求相匹配的路由,将其Web Handler
。Handler
通过指定的过滤器链将请求发送到实际服务,执行业务逻辑,然后返回。如果有post
类型的过滤器,执行过滤器逻辑。
pre类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等功能
。
post类型的过滤器可以做响应内容、响应头的修改、日志输出、流量监控等功能
。
4、入门配置
创建cloud-gateway-gateway9527
模块,修改pom.xml
,加入spring-cloud-starter-gateway
和spring-cloud-starter-netflix-eureka-client
的依赖。
cloud-gateway-gateway9527
模块的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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- 引入父级模块名称 -->
<parent>
<artifactId>cloud2020</artifactId>
<groupId>com.king.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<!-- 子模块名称 -->
<artifactId>cloud-gateway-gateway9527</artifactId>
<dependencies>
<!-- 引用gateway网关服务依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- 引用eureka-client注册服务客户端依赖 -->
<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>
<!-- 引用父级的lombok依赖 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
使用spring-cloud-starter-gateway
依赖时不能添加spring-boot-starter-web
跟spring-boot-starter-actuator
依赖,不然会报错:
cloud-gateway-gateway9527
模块的application.yml
文件:
# 配置服务端口号
server:
port: 9527
# 配置应用信息
spring:
application:
name: cloud-gateway # 配置应用名称
# 配置eureka
eureka:
instance:
hostname: cloud-gateway-service # 实例名称
client:
register-with-eureka: true # true:将自己注册进Eureka
fetch-registry: