GateWay概述
Spring Cloud Gateway是Spring官方基于Spring5.0、SpringBoot2.0和Project Reactor等技术开发的网关。Spring Cloud Gateway旨在为微服务架构提供简单、有效且统一的API路由管理方式。
Zuul1.x基于Servlet实现,采用HttpClient进行请求转发,使用阻塞模式,不支持长连接。Spring Cloud只是将Zuul作为一个组件进行引入使用,并非Spring Cloud子项目。由于Zuul2.x(非阻塞模式)不断的跳票,Spring Cloud推出了全新的服务网关Gateway取代Zuul。
核心组件
路由(Route):路由是服务网关基本组件,由服务实例ID、目标URI、断言集合和过滤器集合共同组成,断言判定为true,匹配服务路由并进行路由转发。
断言(predicate):判定当前请求是否和路由规则匹配,匹配成功(true)执行具体的路由操作,匹配失败返回错误信息。每个断言的入参是Spring框架的ServerWebExchange对象(原理分析章节详细描述)。
过滤器(Filter):使用特定工厂构造的SpringFrameworkGatewayFilter实例,作用是在发送下游请求之前或之后,对请求和响应信息进行修改。
服务网关对比
| Zuul1.x | Gateway |
技术实现 | servlet | Spring5.0+SpringBoot2.0+ProjectReactor |
通信模式 | 阻塞模式 | 非阻塞模式 |
长连接 | 不支持 | 支持 |
限流 | 无 | 内置限流器 |
开发/扩展难度 | 易 | 难 |
Gateway网关创建方式
项目依赖
org.springframework.cloud
spring-cloud-starter-gateway
默认情况下,gateway网关会自动开启,如果不希望自动开启,可以添加配置信息:
#配置为false无法自动注入Gateway路由构建器RouteLocatorBuilder
spring.cloud.gateway.enabled=true
因为Gateway依赖WebFlex,而WebFlex和Spring MVC的包冲突,引入Gateway后在引入spring-boot-starter-web会发生异常。
当前Gateway只能支持Netty容器,不支持其他容器,引入tomcat或jetty容器会在运行期间出现意想不到的问题。
如果选择以WAR包的方式进行打包,需要删除IDE为你创建的ServletInitializer.java(依赖tomcat容器),Gateway使用的是Netty容器
配置类创建
Gateway程序入口
package com.spring.cloud.gateway.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = "com.spring.cloud.gateway.*")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
网关配置类
package com.spring.cloud.gateway.config;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder)
{
//获取Gateway路由构建器
RouteLocatorBuilder.Builder routes=builder.routes();
/**
* 为Gateway路由构建器创建路由规则
* id:微服务实例标识
* path:服务路由访问地址
* uri:服务实例调用地址
*本例中的路由规则:当服务请求路径为/user/**时,将服务路由到实际处理用户服务的服务实例localhost://8100/user
*/
routes.route("user-routes",u->u.path("/user/**").uri("localhost://8100/user")).build();
//返回路由构建器创建的路由定位器
return routes.build();
}
}
配置文件创建
#配置Gateway网关
#配置Gateway网关服务路由标识
spring.cloud.gateway.routes[0].id=user-routes
#配置Gateway网关服务路由uri
spring.cloud.gateway.routes[0].uri=localhost://8100/user
#配置Gateway网关断言为Path断言工厂(匹配服务路由访问地址)
spring.cloud.gateway.routes[0].predicates=Path=/user/**
#配置Gateway网关服务路由标识
spring.cloud.gateway.routes[1].id=order-routes
#配置Gateway网关服务路由uri
spring.cloud.gateway.routes[1].uri=lb://order-routes
#配置Gateway网关断言为Path断言工厂(匹配服务路由访问地址)
spring.cloud.gateway.routes[1].predicates=Path=/order/**
执行流程Zuul执行流程
Zuul会为每一个服务调用请求分配一条线程,通过执行不同类型过滤器去完成服务路由功能。在服务路由执行的过程中,需要通过route过滤器通过服务实例标识匹配服务实例并对匹配到的服务实例进行服务调用,服务实例可能会因为执行复杂的业务处理而导致服务响应慢,造成服务调用线程执行长时间等待,易造成线程积压,导致性能变慢。
Gateway执行流程
系统用户通过Gateway客户端向Spring Cloud Gateway发起服务调用请求,通过HttpWebHandleAdapter提取组装成网关上下文,将网关上下文DispatcherHandler;DispatcherHandler根据断言类型将请求分发给不同的断言处理器进行处理(上图分发给路由断言处理器);路由断言处理器负责根据URI与Gateway Path进行匹配,匹配成功返回对应的FilteringWebHandler;FilteringWebHandler主要负责组装过滤器链并进行一系列的过滤器链调用处理后,转发至具体的被调用服务实例,被调用服务实例处理完毕后,将处理结果返回至Gateway客户端。
Gateway客户端为每一个发起服务调用的请求创建独立的线程,该线程仅仅在发起服务调用请求后就处于挂起状态,不会等待具体的服务调用处理过程,服务调用处理过程有了响应信息后,通过寻址的方式响应之前客户端发送的请求。