SpringCloud Gateway

Posted 司腾

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringCloud Gateway相关的知识,希望对你有一定的参考价值。

使用网关我们会存在什么问题

如果让客户端直接与各个微服务交互,会存在如下问题:

  • 存在跨域请求,在一定场景下处理相对复杂
  • 身份认证问题,每个微服务需要独立认证
  • 某些微服务使用了防火墙或者浏览器不友好的协议,直接访问会有一定困难

网关能给我们解决什么问题

统一接入

  • 为各中无线应用提供统一接入服务
  • 高性能,高并发,高可用性
  • 负载均衡,容灾切换,异地存活

流量管控

  • 服务降级
  • 熔断
  • 路由

安全防护

  • 黑白名单
  • 风控犯刷,防恶意防刷等

协议适配

  • 前端系统(http,https),后端系统(RPC)
  • 长,短链接支持
  • 路由前端请求,响应结果

GateWay网关介绍

Spring Cloud Gateway 即Spring官方推出的一款API网关,该框架包含了Spring5、SpringBoot2、Project Reactor,其中底层通信框架用的netty。Spring Cloud Gateway在推出之初的时候,Netflix公司已经推出了类似功能的API网关框架ZUUL,但ZUUL有一个缺点是通信方式是阻塞的,虽然后来升级到了非阻塞式的ZUUL2,但是由于Spring Cloud Gateway已经推出一段时间,同时自身也面临资料少、维护性较差的因素没有被广泛应用。

相关术语

Route:

即一套路由规则,是集URI、predicate、filter等属性的一个元数据类。\\

Predicate:

这是Java8函数式编程的一个方法,这里可以看做是满足什么条件的时候,route规则进行生效。

Filter:

filter可以认为是Spring Cloud Gateway最核心的模块,熔断、安全、逻辑执行、网络调用都是filter来完成的,其中又细分为gateway filter和global filter,区别在于是具体一个route规则生效还是所有route规则都生效。

路由规则

Path:

Query:

Method:

Datetime:

RemoteAddr:

Header:

使用动态配置(使用Eureka)

### 过滤器

RewritePathGatewayFilterFactory

PrefixPathGatewayFilterFactory

StripPrefixGatewayFilterFactory

SetPathGatewayFilterFactory

AddRequestParameterGatewayFilterFactory

SetStatusGatewayFilterFactory

自定义过滤器

public class CustomGatewayFilter implements GatewayFilter, Ordered 
    /**
     * 过滤业务逻辑
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) 
        System.out.println("自定义网关过滤器");
        return chain.filter(exchange);
    

    /**
     *  过滤器执行顺序,数值越小,优先级越高
     * @return
     */
    @Override
    public int getOrder() 
        return 0;
    

复制代码
@Configuration
public class GatewayRoutesConfiguration 

    public RouteLocator routeLocator(RouteLocatorBuilder builder) 
        return builder.routes().route(r -> (r
                //断言 判断条件
                .path("/order")
                //目标URI
                .uri("lb://app-order")
                //注册自定义过滤器
                .filters(new CustomGatewayFilter())
                //路由id,唯一
                .id("app-order")
        )).build();
    

复制代码

自定义全局过滤器

@Component
public class CustomGlobalFilter implements GlobalFilter, Ordered 
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) 
        System.out.println("自定义全局过滤器");
        return chain.filter(exchange);
    

    @Override
    public int getOrder() 
        return 0;
    

复制代码

源码解析

上图是Spring Cloud Gateway官方文档给出的一个工作原理图,Spring Cloud Gateway 接收到请求后进行路由规则的匹配,然后交给web handler 进行处理,web handler 会执行一系列的filter逻辑。

入口

Gateway的编程模式是webflux+reactor,我对这一块能力有限,能不解释就不解释了(汗) org.springframework.web.reactive.DispatcherHandler#handle

public Mono<Void> handle(ServerWebExchange exchange) 
   if (this.handlerMappings == null) 
      return createNotFoundError();
   
   return Flux.fromIterable(this.handlerMappings)
         .concatMap(mapping -> mapping.getHandler(exchange))
         .next()
         .switchIfEmpty(createNotFoundError())
         .flatMap(handler -> invokeHandler(exchange, handler))
         .flatMap(result -> handleResult(exchange, result));

复制代码

所有webflux的调用都会走这个接口.

这么多实现类,只有这一个是gateway的,就它了.

private Route convertToRoute(RouteDefinition routeDefinition) 
//从配置文件中获取predicates
   AsyncPredicate<ServerWebExchange> predicate = combinePredicates(routeDefinition);
   // 从配置文件中获取filters
   List<GatewayFilter> gatewayFilters = getFilters(routeDefinition);
// 封装路由里的内容,返回对象
   return Route.async(routeDefinition).asyncPredicate(predicate)
         .replaceFilters(gatewayFilters).build();

复制代码


protected Mono<Route> lookupRoute(ServerWebExchange exchange) 
   return this.routeLocator.getRoutes()
         // individually filter routes so that filterWhen error delaying is not a
         // 请求进来的接口与路由规则进行匹配
         .concatMap(route -> Mono.just(route).filterWhen(r -> 
            // add the current route we are testing
            exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, r.getId());
            return r.getPredicate().apply(exchange);
         )


复制代码

一路返回

org.springframework.web.reactive.DispatcherHandler#handle

public Mono<Void> handle(ServerWebExchange exchange) 
//从之前放到上下文中取出
   Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
   //获取对应路由的过滤器
   List<GatewayFilter> gatewayFilters = route.getFilters();
    //获取全局过滤器
   List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);
   //添加到全局过滤器当中
   combined.addAll(gatewayFilters);
   // 排序
   AnnotationAwareOrderComparator.sort(combined);

   if (logger.isDebugEnabled()) 
      logger.debug("Sorted gatewayFilterFactories: " + combined);
   
//最经典的责任链调用,将每一个全局过滤器都执行一遍
   return new DefaultGatewayFilterChain(combined).filter(exchange);

复制代码

请求转发

ForwardRoutingFilter做的事情也很简单,直接复用了spring mvc的能力,将请求提交给dispatcherHandler进行处理,dispatcherHandler会根据path前缀找到需要目标处理器执行逻辑.

响应回写

响应回写的核心类是NettyWriteResponseFilter

结语

只是过了一下大体的流程,细节要根据具体情况再继续分析,对reactor编程方式不是很熟,导致很多地方都只能理解大概,后期会填补这一块的.


 

以上是关于SpringCloud Gateway的主要内容,如果未能解决你的问题,请参考以下文章

springcloud01-SpringCloud 概述

SpringCloud系列SpringCloud概述及微服务技术栈的使用

springcloud2020版本使用zuul和nacos服务发现

springcloud情操陶冶-初识springcloud

SpringCloud学习系列-SpringCloud

springcloud nacos 跨服务调用失败