1、Gateway概述简介
官网:Gateway网关官网
Gateway是什么
Gateway
是在Spring
生态系统之上构建的API网关服务,基于Spring 5,Spring Boot 2和Project Reactor
等技术。Gateway
旨在提供一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤器功能,例如:熔断、限流、重试等。SpringCloud Gateway
是Spring Cloud
的一个全新项目,基于Spring 5.0+Spring Boot 2.0和Project Reactor
等技术开发的网关,它旨在为微服务架构提供—种简单有效的统一的API路由管理方式
SpringCloud Gateway作为Spring Cloud
生态系统中的网关,目标是替代Zuul
,在Spring Cloud 2.0
以上版本中,没有对新版本的Zul 2.0
以上最新高性能版本进行集成,仍然还是使用的Zuul 1.x非Reactor模式
的老版本。而为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty
。- Spring Cloud Gateway的目标是提供统一的路由方式且基于 Filter链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。
Gateway能干什么
- 反向代理
- 鉴权
- 流量控制
- 熔断
- 日志监控
Gateway网关在微服务架构中的位置
GateWay是基于异步非阻塞模型上进行开发的, 它的特性都有什么呢?
- 基于
Spring Framework 5,Project Reactor和Spring Boot 2.0
进行构建; - 动态路由:能够匹配任何请求属性
- 可以对路由指定
Predicate (断言)和Filter(过滤器)
- 集成
Hystrix
的断路器功能 - 集成
Spring Cloud
服务发现功能 - 易于编写的
Predicate (断言)和Filter (过滤器)
- 请求限流功能
- 支持路径重写
Spring Cloud Gateway与Zuul的区别
- 在
SpringCloud Finchley
正式版之前,Spring Cloud推荐的网关是Netflix提供的Zuul
- Zuul 1.x,是一个基于阻塞I/O的API Gateway
- Zuul 1.x基于Servlet 2.5使用阻塞架构它不支持任何长连接(如WebSocket)Zuul的设计模式和Nginx较像,每次I/О操作都是从工作线程中选择一个执行,请求线程被阻塞到工作线程完成,但是差别是Nginx用C++实现,Zuul用Java实现,而JVM本身会有第-次加载较慢的情况,使得Zuul的性能相对较差
-
Spring Cloud Gateway
建立在Spring Framework 5、Project Reactor和Spring Boot2
之上,使用非阻塞API
-
Spring Cloud Gateway
还支持WebSocket
,并且与Spring
紧密集成拥有更好的开发体验
2、三大核心概念
Route路由
路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成
,如断言为true则匹配该路由
Predicate断言
参考的是Java8的java.util.function.Predicate
,开发人员可以匹配HTTP
请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由
Filter过滤
指的是Spring框架中GatewayFilter
的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。
- web请求,通过一些匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。
predicate
就是我们的匹配条件;fliter
就可以理解为一个无所不能的拦截器。有了这两个元素,再加上目标url
,就可以实现一个具体的路由了
3、Gateway工作流程
- 客户端向
Spring Cloud Gateway
发出请求。然后在Gateway Handler Mapping
中找到与请求相匹配的路由,将其发送到GatewayWeb Handler
Handler
再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回- 过滤器之间用
虚线分开
Filter
在“pre”类型(之前)
的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等
,在“post”类型(之后)
的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等
- 核心逻辑:路由转发 + 执行过滤链
4、Gateway入门配置
新建spring-cloud-starter-gateway项目
修改pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http:///POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http:///POM/4.0.0 http:///xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud2020</artifactId>
<groupId>com.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-gateway-gateway9572</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<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>
<!-- 引入自己定义的api通用包,可以使用Paymeny支付Entity -->
<dependency>
<groupId>com.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
写yml文件
server:
port: 9527
spring:
application:
name: cloud-gateway
eureka:
instance:
hostname: cloud-gateway-service
client:
service-url:
register-with-eureka: true
fetch-registry: true
defaultZone:
http://:7001/eureka
主启动类
@SpringBootApplication
@EnableEurekaClient
public class GateWayMain9527 {
public static void main(String[] args) {
SpringApplication.run(GateWayMain9527.class, args);
}
}
yml文件中新增网关配置
那么spring-cloud-starter-gateway如何做路由映射呢?我们目前不想暴露8001端口,希望在8001外面套一层9527
server:
port: 9527
spring:
application:
name: cloud-gateway
###############################新增网关配置####################################
cloud:
gateway:
routes: # 网关可以配置多个
- id: payment_routh # 路由的id,没有固定的规则但要求唯一,建议配合服务名
uri: http://localhost:8001 # 匹配后提供服务的路由地址
predicates:
- Path=/payment/get/**
##############################################################################
eureka:
instance:
hostname: cloud-gateway-service
client:
service-url:
register-with-eureka: true
fetch-registry: true
defaultZone:
http://:7001/eureka
启动测试:启动7001,8001,9527
- 添加网关前:
http://localhost:8001/payment/get/1
- 添加网关后:
http://localhost:9527/payment/get/1
- 结论:两者访问成功,并且返回结果相同
5、Gateway配置路由的两种方式
- 在配置文件中
yml文件
中配置 - 代码中实现:
注入RouteLocator的Bean
- 官网的实现方式:实现方式
RemoteAddressResolver resolver = XForwardedRemoteAddressResolver
.maxTrustedIndex(1);
...
.route("direct-route",
r -> r.remoteAddr("10.1.1.1", "10.10.1.1/24")
.uri("https://downstream1")
.route("proxied-route",
r -> r.remoteAddr(resolver, "10.10.1.1", "10.10.1.1/24")
.uri("https://downstream2")
)
我们通过代码去实现——通过9527网关访问到一个网址
@Configuration
public class GateWayConfig {
/**
* 配置了一个id为path_route的路由规则
* 当前访问地址为http://localhost:9527/guonei时,会自动转发到地址https:///guonei
*
* @param routeLocatorBuilder
* @return
*/
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
routes.route("path_route",
r -> r.path("/guonei")
.uri("https:///guonei")).build();
return routes.build();
}
}
测试
访问http://localhost:9527/guonei
,返回http:///guonei
相同的页面。
6、GateWay常用的Predicate(断言)
- 官网链接:官网
Spring Cloud Gateway matches routes as part of the Spring WebFlux HandlerMapping infrastructure. Spring Cloud Gateway includes many built-in route predicate factories. All of these predicates match on different attributes of the HTTP request. You can combine multiple route predicate factories with logical and statements.
Spring Cloud GateWay
将路由匹配作为Spring WebFlux HandlerMapping
基础架构的一部分。Spring Cloud GateWay
包括许多内置的Route Predicate
工厂。所有这些Predicate
都与HTTP
请求的不同属性匹配。多个Route Predicate
工厂可以进行组合。Spring Cloud GateWay
创建Route
对象时,使用RoutePredicateFactory
创建Predicate
对象,Predicate
对象可以赋值给Route
。Spring Cloud GateWay
包含许多内置的RoutePredicateFactory
- 所有这些谓词都匹配HTTP请求的不同属性。多种谓词工厂可以组合,并通过逻辑and
- 常用的Route Predicate Factory
The After Route Predicate Factory
The Before Route Predicate Factory
The Between Route Predicate Factory
The Cookie Route Predicate Factory
The Header Route Predicate Factory
The Host Route Predicate Factory
The Method Route Predicate Factory
The Path Route Predicate Factory
The Query Route Predicate Factory
The RemoteAddr Route Predicate Factory
The weight Route Predicate Factory
The After Route Predicate Factory
- 官网配置示例:
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
# 在这个时间之后才会生效
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
-
2017-01-20T17:42:47.789-07:00[America/Denver]
:美国时间 -
ZonedDateTime.now()
:从默认时区中的系统时钟获取当前日期时间。 -
2022-02-25T16:50:23.358+08:00[Asia/Shanghai]
:当前时间
The Cookie Route Predicate Factory
The cookie route predicate factory takes two parameters, the cookie name and a regular expression. This predicate matches cookies that have the given name and whose values match the regular expression. The following example configures a cookie route predicate factory
- 官网配置示例:
spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: https://example.org
predicates:
- Cookie=chocolate, ch.p
-
Cookie Route Predicate
需要两个参数,一个是Cookie name
,一个是正则表达式
- 路由规则会通过获取对应的
Cookie name值和正则表达式