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以上版本中,没有对新版本的 Zuul 2.0 以上最新高性能版本进行集成,仍然还是使用的Zuul 1.x非Reactor模式的老版本。而为了提升网关的性能,SpringCloud Gateway 是基于 WebFlux 框架实现的,而 WebFlux 框架底层则使用了高性能的 Reactor 模式通信框架 Netty。

微服务中的网关位置

image

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/ O 操作都是从工作线程中选择一个执行,请求线程被阻塞到工作线程完成,但是差别是Nginx 用C++ 实现,Zuul 用 Java 实现,而 JVM 本身会有第一次加载较慢的情况,使得Zuul 的性能相对较差。
  • Zuul 2.x理念更先进,想基于Netty非阻塞和支持长连接,但SpringCloud目前还没有整合。 Zuul 2.x的性能较 Zuul 1.x 有较大提升。在性能方面,根据官方提供的基准测试,Spring Cloud Gateway 的 RPS 是 Zuul 的 1.6 倍。
  • Spring Cloud Gateway 建立在 Spring Framework 5,Project Reactor 和 Spring Boot 2 之上,使用非阻塞 API。
  • Spring Cloud Gateway 还支持 WebSocket,并且与 Spring 紧密集成拥有更好的开发体验。

WebFlux是什么?

传统的Web框架,比如说:struts2,springmvc等都是基于Servlet API与Servlet容器基础之上运行的。

但是在 Servlet3.1 之后有了异步非阻塞的支持。而 WebFlux 是一个典型非阻塞异步的框架,它的核心是基于Reactor 的相关 API 实现的。相对于传统的 web 框架来说,它可以运行在诸如 Netty,Undertow 及支持Servlet3.1 的容器上。非阻塞式+函数式编程( Spring5 必须让你使用 java8)

Spring WebFlux 是 Spring 5.0 引入的新的响应式框架,区别于 Spring MVC,它不需要依赖 Servlet API,它是完全异步非阻塞的,并且基于 Reactor 来实现响应式流规范。

Gateway 的核心概念

Route(路由)

路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由;

Predicate(断言)

参考的是Java8的 java.util.function.Predicate 开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由;

Filter(过滤)

指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。

总结

web 请求,通过一些匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。predicate 就是我们的匹配条件;而 filter,就可以理解为一个无所不能的拦截器。有了这两个元素,再加上目标 uri,就可以实现一个具体的路由了;

大致流程

客户端向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。

Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。

过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。Filter在“pre”类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在“post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。

案例

导包

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

修改配置文件

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由

        - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/lb/**         # 断言,路径相匹配的进行路由
            #- After=2020-02-21T15:51:37.485+08:00[Asia/Shanghai]
            #- Cookie=username,zzyy
            #- Header=X-Request-Id, /d+  # 请求头要有X-Request-Id属性并且值为整数的正则表达式

配置类的方法

@Configuration
public class GatewayConfig {

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
        routes.route("path_route_atguigu",
                r -> r.path("/guonei")
                        .uri("https://news.baidu.com/guonei")).build();

        return routes.build();
    }
}

Predicate 使用

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 包含许多内置的Route Predicate Factories。

所有这些谓词都匹配HTTP请求的不同属性。多种谓词工厂可以组合,并通过逻辑and。

常用的Route Predicate

  • 请求时间校验条件(datetime):

    • After Route Predicate:请求时间满足在配置时间之后。
    • Before Route Predicate:请求时间满足在配置时间之前。
    • Between Route Predicate:请求时间满足在配置时间之间。
  • 请求 Cookie校验条件(Cookie):

    • Cookie Route Predicate:请求指定 Cookie 正则匹配指定值
      • 需要两个参数,一个是 Cookie name,一个是正则表达式。
  • 请求 Header 校验条件(Header):

    • Header Route Predicate:请求指定 Header 正则匹配指定值;

      • 两个参数:一个是属性名称和一个正则表达式,这个属性值和正则表达式匹配执行。

      • curl http://localhost:9527/payment/lb -H "X-Request-Id:123"
        
    • CloudFoundryRouteServiceRoutePredicateFactory:请求 Headers 是否包含指定的名称。

  • 请求 Host 校验条件(Host):

    • Host Route Predicate:请求 Host 匹配指定值;
  • 请求 Method 校验条件(Method):

    • Method Route Predicate:请求 Method 匹配配置的 method;
  • 请求 Path 校验条件(Path):

    • Path Route Predicate:请求路径正则匹配指定值;
  • 请求查询参数校验条件(Queryparam):

    • Query Route Predicate:请求查询参数正则匹配指定值;
  • 请求远程地址校验条件(RemoteAddr):

    • RemoteAddrRoutePredicateFactory:请求远程地址匹配配置指定值;

Filter 的使用

路由过滤器可用于修改进入的HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用。Spring Cloud Gateway 内置了多种路由过滤器,他们都由GatewayFilter的工厂类来产生;

Filter 的分类

生命周期
  • pre
  • post
种类
  • GatewayFilter
  • GlobalFilter

自定义过滤器

主要实现:全局日志记录、统一网关鉴权等服务;

案例
@Component
@Slf4j
public class MyLogGatewayFilter implements GlobalFilter, Ordered {


    @Override
    public Mono <Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("-------------------- come in MyLogGatewayFilter:{}", new Date());
        String uname = exchange.getRequest().getQueryParams().getFirst("uname");
        if (uname == null) {
            log.info("---------------- 用户名为 null,非法用户,┭┮﹏┭┮");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

原创文章,作者:carmelaweatherly,如若转载,请注明出处:https://blog.ytso.com/245557.html

(0)
上一篇 2022年4月18日
下一篇 2022年4月18日

相关推荐

发表回复

登录后才能评论