zoukankan      html  css  js  c++  java
  • 微服务之服务网关Gateway

    一、什么是Gateway?

      Gateway是Spring生产系统上构建的API服务网关,基于Spring5、SpringBoot2和ProjectReactor等技术。它的目标是提供一种简单有效的方式对API进行路由,以及提供一些强大的过滤器功能,包括熔断、限流、重试等。

      SpringCloud Gateway是SpringCloud的一个全新项目,基于WebFlux框架实现的,而webFlux底层使用了高性能的Reactor模式通信框架Netty。SpringCloud Gateway为微服务架构提供一种简单有效的统一的API路由管理方式,目的是为了替代Zuul成为全新一代的服务网关。

      前面提到了服务网关,那什么又是服务网关呢?它是一个网络关口、通道,是整个微服务平台所有请求的统一入口,所有的客户端和服务消费端都只能通过这个关口来访问微服务。除了作为统一入口之外,它还可以处理非业务功能,承担认证授权、访问控制、路由、负载均衡、日志、缓存、映射、过滤、熔断、注册、服务编排、API管理、监控、统计分析等职责。所以选择一个优秀的服务网关对于开发微服务体系系统至关重要。以下是借鉴某伙伴的服务架构图:

     二、Gateway的工作流程

      要理解工作流程,先了解以下三个核心名词

        1、Route路由:路由是构建网关的基本模块,由一系列的断言和过滤器组成,如果断言为true则匹配该路由。

        2、predicate断言:预先设置的规则条件。开发人员可以匹配http请求中的内容,如果请求与断言相匹配则进行路由匹配。

        3、Filte过滤器:过滤器是GatewayFilter的一个实例,它可以在请求被路由前后完成对请求的修改。Gateway中存在一系列过滤链,用于完成不同的处理(请求前可以做权限校验、流量监控、日志输出、协议转换等,请求后响应内容修改等)。

      一个web请求进来,Gateway首先会进行条件匹配,定位真正的服务节点,并在转发web请求的前后进行一些额外的处理,这些处理就通过过滤器来实现,而前面的匹配就是通过断言来实现。以下是网关内部的工作流程图

      三、服务网关模块的搭建

      搭建服务网关模块的步骤:

      1、引入jar包:除了引入gateway的jar包外,网关本身也是一种微服务,也需要注册到服务注册中心,因此还需要引入相应的注册中心客户端jar包,进行相应的配置(配置方式参考服务注册中心相关文档)。最后要注意的是,作为网关的模块请不要引入

    与spring-boot-starter-web相关的包,否则会出现冲突报错。

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

       2、修改application.yml文件,配置网关路由规则。路由是多个,可以配置在routes节点下,如图所示表示配置了两个路由规则: 

    server:
      port: 9527
    
    spring:
      application:
         name: cloud-gateway
      cloud:
         gateway:
            routes:
               - id: payment_routh                     #路由的ID,没有固定规则但要求唯一,建议配合服务名
                 uri: http://localhost:8001            #匹配后提供服务的路由地址
                 predicates:  
    - Path=/payment/get/** #断言,路径相匹配的进行路由 - id: payment_routh2 #路由的ID,没有固定规则但要求唯一,建议配合服务名 uri: http://localhost:8001 #匹配后提供服务的路由地址 predicates:
    - Path=/payment/lb/** #断言,路径相匹配的进行路由

       当进行上述配置后,我们就可以不直接访问http://localhost:8001/payment/get/来调用微服务,而是通过http://localhost:9527/payment/get/来间接调用8001微服务。当客户端访问http://localhost:9527/****/***时,网关服务模块就根据路由规则进行匹配,从而调用不同的微服务(网关服务模块获取到请求地址后,用请求地址去断言,断言uri指定的微服务下是否存在predicates指定的路径模式,如果为true则调用)。

       3、完成以上两步,启动网关服务模块,客户端向微服务的请求全部通过访问该服务来实现,到此简单的网关服务模块搭建完成。

      除了2中配置文件实现路由配置的方式外,还可以通过硬编码的方式(代码中注入RouteLocator的Bean)来实现路由匹配:新建网关配置文件GatewayConfig类,写入如下类似代码即可

    @Configuration
    public class GatewayConfig
    { @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder)
    { RouteLocatorBuilder.Builder routes
    = routeLocatorBuilder.routes();
    routes.route(
    id: "path_route_name", r -> r.path("/aaaa").uri("http://xxx.com/bbbb") /* /aaaa路径将会被路由到http://xxx.com/bbbb */
    ).build();
      return routes.build();
    }

     四、动态路由配置

      默认情况下,Gateway会根据注册中心注册的服务列表,以微服务的名称为路径创建动态路由进行转发,实现动态路由功能。开启动态路由只需要在上述简单路由的基础上修改yml配置文件,开启动态路由功能即可,要注意创建动态路由时uri要写成服务名称的形式,如下所示:

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

     五、Gateway过滤器Filter

      过滤器允许以某种方式修改传入的HTTP请求或返回的HTTP响应。过滤器作用于某些特定路由。Spring Cloud Gateway包括许多内置的 Filter工厂,这些工厂负责创建Filter过滤器实例,同时也支持自定义过滤器。多个过滤器结合使用可以形成过滤器链对http请求进行处理。

      1、内置的过滤器:分为单一过滤器GatewayFilter和全局过滤器GlobalFilter,作用于业务逻辑之前或业务逻辑之后。使用方式与断言类似,通过配置实现过滤功能,yml配置参考代码如下

    server:
      port: 9527
    
    spring:
      application:
         name: cloud-gateway
      cloud:
         gateway:
            discovery:
               locator :
                 enabled: true 
            routes:
               - id: payment_routh                     
                 uri: http://cloud-server-name         
    filters:
    - AddRequestParameter=X-Request-Id,1024 #过搪器工厂会在匹配的请求头加上一对请求头,名称为X-Request-Id值为1024
    predicates:
    - Path=/payment/get/**

        2、自定义全局过滤器:新建MyGatewayFilter类,实现GlobalFilter,Orderd接口,重写filter方法和getOrder方法,参考代码如下

    @Component
    public class MyGatewayFilter implements GlobalFilter,ordered  /*实现接口*/
    {
        @override
         public Mono<Void> filter(ServerwebExchange exchange,GatewayFilterchain chain) /*exchange是请求的上下文,chain表示下一过滤器*/
    {
    string uname = exchange.getRequest().getQueryParams( ).getFirst( key: "uname");
    if(uname == nul1) { exchange.getResponse().setstatuscode(Httpstatus.NOT_ACCEPTABLE);
    return exchange.getResponse().setcomplete(); /*如果uname为空,则设置状态为不被接受,然后返回结果*/ } return chain.filter(exchange); /*继续执行下一过滤器*/ } @Override public int getorder()
    {
    return 0; /*设置过滤器顺序*/
    }
    }

       以上代码的作用是过滤非法用户,只需完成以上编码,无需额外配置即可实现全局过滤功能。内置的过滤器此处不再详述。

    六、Gateway常用的断言Predicate

      分析前面的yml配置文件,发现predicates是复数形式,表明我们可以设置多个断言,进行更精确的匹配。Gateway提供了如下几种断言规则:

    规则 配置格式 说明
    After

    - After=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]

    匹配在此时间之后的访问
    Before - Before=2020-02-05T15:10:03.685+08:00[Asia/Shanghai] 匹配在此时间之前的访问
    Between - Between=2020-02-05T15:10:03.685+08:00[Asia/Shanghai], 2020-02-05T15:10:03.685+08:00[Asia/Shanghai] 匹配在该时间段的访问
    Cookie - Cookie=username,zhangsan 匹配cookie名称为zhangsan
    Header - Header=X-Request-Id,d+ 匹配请求头要有x-Request-Id属性并且值为整数
    Host - Host=**.yy.com 匹配主机名为.yy.com
    Method - Method=Get 匹配get请求
    Path - Path=/payment/get/** 匹配路径
    Query - Query=username,d+ 匹配查询字符串存在username并且值为整数
    RemoteAddr - RemoteAddr =192.168.0.1/16 匹配Remote Adress为192.168.0.1
  • 相关阅读:
    kubernetes-handbook 阅读笔记
    kubernetes-notes--阅读笔记
    SpringInAction4笔记——复习
    spring源码解析——2容器的基本实现(第2版笔记)
    把node加入master节点时,日志内容分析
    初始化master节点时,日志内容分析
    Mac OS用minikube安装单节点kubernetes
    Mac OS用vmvare安装多节点kubernetes
    FatMouse's Speed 基础DP
    FatMouse and Cheese 动态化搜索
  • 原文地址:https://www.cnblogs.com/zqhIndex/p/15402043.html
Copyright © 2011-2022 走看看