SpringCloud 系列(九)------ Gateway 网关

目录

网关定义

网关的功能

Zuul 与 Spring Cloud Gateway 比较

Spring Cloud GateWay 架构图

Spring Cloud Gateway 的几个概念

快速开始

Spring Cloud Gateway作为Spring Cloud框架的第二代网关,在功能上要比 Zuul更加的强大,性能也更好。随着 Spring Cloud的版本迭代,Spring Cloud官方有打算弃用 Zuul的意思。在笔者调用了Spring Cloud Gateway的使用和功能上,Spring Cloud Gateway替换掉 Zuul的成本上是非常低的,几乎可以无缝切换。Spring Cloud Gateway几乎包含了zuul的所有功能。

网关定义

API 网关是一个反向路由:屏蔽内部细节,为调用者提供统一入口,接收所有调用者请求,通过路由机制转发到服务实例。
API网关是一组“过滤器”集合:可以实现一系列与核心业务无关的横切面功能,如安全认证、限流熔断、日志监控。
网关在系统中所处的位置:

网关的功能

Zuul 与 Spring Cloud Gateway 比较

 优点缺点
Gateway

1、线程开销小

2、使用轻量级 netty 异步io实现通信

3、支持各种长连接,websocket

4、spring 官方推荐,重点支持,功能较Zuul更丰富,支持限流监控等

1、源码复杂

2、运维复杂

3、目前资料、实践较少,出现问题排查难度大

Zuul

1、编码模型简单

2、开发调试运维简单

1、线程上下文切换开销

2、线程数限制

3、延迟堵塞耗尽线程链接资源

Zuul 与  Spring Cloud Gateway 压测结果:休眠时间模仿后端请求时间,线程数 2000,请求时间 360秒=6分钟。配置情况:Gateway 默认配置,Zuul网关的 Tomcat 最大线程数为 400,hystrix 超时时间为 100000。

休眠时间

测试样本,单位=个

Zuul/Gateway

平均响应时间,单位=毫秒

Zuul/Gateway

99%响应时间,单位=毫秒
Zuul/Gateway

错误次数,单位=个

Zuul/Gateway

错误比例

Zuul/Gateway

休眠100ms294134/10593212026/5466136/1774104/00.04%/0%
休眠300ms101194/3999095595/148915056/16901114/01.10%/0%
休眠600ms51732/20126211768/297527217/32032476/04.79%/0%
休眠1000ms31896/12095619359/491446259/51153598/011.28%/0%

测试结果:Gateway在高并发和后端服务响应慢的场景下比 Zuul的表现要好 

Spring Cloud GateWay 架构图

如上图所示,客户端向 Spring Cloud Gateway发出请求。 如果 Gateway Handler Mapping确定请求与路由匹配这个时候就用到 predicate),则将其发送到 Gateway web handler处理。 Gateway web handler处理请求时会经过一系列的过滤器链。 过滤器链被虚线划分的原因是过滤器链可以在发送代理请求之前或之后执行过滤逻辑。 先执行所有“pre”过滤器逻辑,然后进行代理请求。 在发出代理请求之后,收到代理服务的响应之后执行“post”过滤器逻辑。这跟zuul的处理过程很类似。在执行所有“pre”过滤器逻辑时,往往进行了鉴权、限流、日志输出等功能,以及请求头的更改、协议的转换;转发之后收到响应之后,会执行所有“post”过滤器的逻辑,在这里可以响应数据进行了修改,比如响应头、协议的转换等。在上面的处理过程中,有一个重要的点就是将请求和路由进行匹配,这时候就需要用到predicate,它是决定了一个请求走哪一个路由。

Spring Cloud Gateway 的几个概念

【1】Route 路由:gateway的基本构建模块,它由ID、目标URL、断言集合和过滤器集合组成。如果聚合断言结果为真,则匹配到该路由。Gateway 依赖如下:

Route 路由-动态路由实现:网关管理平台实现增删改查路由信息到 mysql。网关管理平台发布,发布后将路由信息通过配置中心 openapi 保存到配置中心服务中。网关监听配置中心配置变化,动态刷新到内存中
 

【2】Predicate 断言:这是一个Java 8 Function Predicate。输入类型是 Spring Framework ServerWebExchange。这允许开发人员可以匹配来自 HTTP请求的任何内容,例如 Header或参数。Predicate 接受一个输入参数,返回一个布尔值结果。Spring Cloud Gateway内置了许多Predict,这些 Predict的源码在 org.springframework.cloud.gateway.handler.predicate包中,如果读者有兴趣可以阅读一下。现在列举各种 Predicate如下图:

在上图中,有很多类型的 Predicate,比如说时间类型的 Predicated(AfterRoutePredicateFactory BeforeRoutePredicateFactory BetweenRoutePredicateFactory),当只有满足特定时间要求的请求会进入到此 predicate中,并交由 router处理;cookie类型的CookieRoutePredicateFactory,指定的 cookie满足正则匹配,才会进入此 router;以及host、method、path、querparam、remoteaddr类型的 predicate,每一种 predicate都会对当前的客户端请求进行判断,是否满足当前的要求,如果满足则交给当前请求处理。如果有很多个Predicate,并且一个请求满足多个Predicate,则按照配置的顺序第一个生效。

Predicate 断言配置:

server:
  port: 8081
spring:
  profiles:
    active: after_route

---
spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: http://bin.org:80/get
        predicates:
        - After=2017-01-20T17:42:47.789-07:00[America/Denver]
  profiles: after_route

在上面的配置文件中,配置了服务的端口为8081,配置 spring.profiles.active:after_route指定了程序的 spring的启动文件为after_route文件。在 application.yml再建一个配置文件,语法是三个横线,在此配置文件中通过 spring.profiles来配置文件名,和spring.profiles.active一致,然后配置 spring cloud gateway 相关的配置,id标签配置的是 router的 id,每个 router都需要一个唯一的id,uri配置的是将请求路由到哪里,本案例全部路由到http://bin.org:80/get。

predicates:After=2017-01-20T17:42:47.789-07:00[America/Denver] 会被解析成 PredicateDefinition对象name =After ,args= 2017-01-20T17:42:47.789-07:00[America/Denver])。在这里需要注意的是 predicates的 After这个配置,遵循的契约大于配置的思想,它实际被 AfterRoutePredicateFactory这个类所处理,这个 After就是指定了它的 Gateway web handler类为AfterRoutePredicateFactory,同理,其他类型的predicate也遵循这个规则。当请求的时间在这个配置的时间之后,请求会被路由到指定的URL。跟时间相关的predicates还有 Before Route Predicate FactoryBetween Route Predicate Factory,读者可以自行查阅官方文档,再次不再演示。

【3】Filter 过滤器:方案一:写死在代码中

@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
	return builder.routes()
		//openapi路由转发
		.route("openapi_route", p -> p.path( "/openapi/**").filters(f->f.removeRequestHeader("Expect"))
		.uri("lb://order-openapi-service"))
		.build();
}

方案二:配置文件(yml)

 # gateway 的配置形式
 routes:
 - id: order-service
   uri: lb://order-service
 predicates:
 - Path=/order/**
   filters:
 - ValidateCodeGatewayFilter

filter 过滤器:filter 按处理顺序 Pre Filter / Post Filter

filter 按作用范围分为:GlobalFilter 全局过滤器。GatewayFilter 指定路由的过滤器。
filter 过滤器-扩展自定义filter:filter 支持通过 spi 扩展。实现 GatewayFilter,Ordered接口。filter 方法:过滤器处理逻辑。getOrder:定义优先级,值越大优先级越低。

public class TokenFilter implements GlobalFilter, Ordered {

    Logger logger=LoggerFactory.getLogger( TokenFilter.class );
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getQueryParams().getFirst("token");
        if (token == null || token.isEmpty()) {
            logger.info( "token is empty..." );
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -100;
    }
}

快速开始

网关启动步骤(代码演示):
【1】添加依赖

 <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-gateway</artifactId>
 </dependency>

【2】添加注释
【3】配置文件

©️2020 CSDN 皮肤主题: 鲸 设计师:meimeiellie 返回首页