Spring Cloud - 网关

  • 介绍

    在分布式环境中,服务之间需要相互通信。但是,这是服务间通信。我们还有一些用例,我们域外的客户想要访问我们的 API 服务。因此,要么我们可以公开所有可由客户端调用的微服务的地址,要么我们可以创建一个服务网关,将请求路由到各种微服务并响应客户端。
    在这里创建网关是更好的方法。有两个主要优点 -
    • 不需要维护每个单独服务的安全性。
    • 而且,横切关注点,例如元信息的添加可以在一个地方处理。
    Netflix ZuulSpring Cloud Gateway是两个著名的云网关,用于处理此类情况。在本教程中,我们将使用 Spring Cloud Gateway。
  • Spring Cloud Gateway – 依赖设置

    让我们以我们一直在使用的 Restaurant 为例。让我们在我们的两个服务,即餐厅服务和客户服务之前添加一个新服务(网关)。首先,让我们更新pom.xml 具有以下依赖项的服务 -
    
    
    <dependencies>
    
       <dependency>
    
             <groupId>org.springframework.cloud</groupId>
    
             <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    
       </dependency>
    
       <dependency>
    
             <groupId>org.springframework.cloud</groupId>
    
             <artifactId>spring-cloud-starter-gateway</artifactId>
    
       </dependency>
    
    </dependencies>
    
    
    然后,使用正确的注释来注释我们的 Spring 应用程序类,即@EnableDiscoveryClient。
    
    
    package com.jc2182;
    
    import org.springframework.boot.SpringApplication;
    
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    
    @SpringBootApplication
    
    @EnableDiscoveryClient
    
    public class RestaurantGatewayService{
    
       public static void main(String[] args) {
    
          SpringApplication.run(RestaurantGatewayService.class, args);
    
       }
    
    }
    
    
    我们使用 @EnableDiscoveryClient 进行注释,因为我们想使用 Eureka 服务发现来获取为特定用例提供服务的主机列表
  • 带网关的动态路由

    Spring Cloud Gateway 具有三个重要部分。这些是 -
    • 路由 - 这些是网关的构建块,其中包含要转发请求的 URL 以及应用于传入请求的谓词和过滤器。
    • 谓词- 这些是一组标准,应与要转发到内部微服务的传入请求相匹配。例如,只有当传入的 URL 包含该路径时,路径谓词才会转发请求。
    • 过滤器 - 在将请求发送到内部微服务或响应客户端之前,您可以在这些地方修改传入的请求。
    让我们为餐厅和客户服务的网关编写一个简单的配置。
    
    
    spring:
    
       application:
    
          name: restaurant-gateway-service
    
       cloud:
    
          gateway:
    
          discovery:
    
             locator:
    
                enabled: true
    
          routes:
    
             - id: customers
    
                uri: lb://customer-service
    
                predicates:
    
                - Path=/customer/**
    
             - id: restaurants
    
                uri: lb://restaurant-service
    
                predicates:
    
                - Path=/restaurant/**
    
    server:
    
       port: ${app_port}
    
    eureka:
    
       client:
    
          serviceURL:
    
             defaultZone: http://localhost:8900/eureka
    
    
    Points to note about the above configuration −
    • 我们启用了 discovery.locator 以确保网关可以从 Eureka 服务器读取。
    • 我们在这里使用了 Path 谓词来路由请求。这意味着任何以 / 开头的请求customer 将被路由到客户服务和 /restaurant,我们会将该请求转发给餐厅服务。
    现在让我们在网关服务之前设置其他服务 -
    • 启动尤里卡服务器
    • 启动客户服务
    • 启动餐厅服务
    现在,让我们编译并执行 Gateway 项目。我们将使用以下命令进行相同的操作 -
    
    
    java -Dapp_port=8084 -jar .\target\spring-cloud-gateway-1.0.jar
    
    
    完成后,我们准备好在端口 8084 上测试网关。让我们首先点击 http://localhost:8084/customer/1,我们看到请求被正确路由到客户服务,我们得到以下输出 -
    
    
    {
    
       "id": 1,
    
       "name": "Jane",
    
       "city": "DC"
    
    }
    
    
    现在,点击我们的餐厅 API,即 http://localhost:8084/restaurant/customer/1,我们得到以下输出 -
    
    
    [
    
       {
    
          "id": 1,
    
          "name": "Pandas",
    
          "city": "DC"
    
       },
    
       {
    
          "id": 3,
    
          "name": "Little Italy",
    
          "city": "DC"
    
       }
    
    ]
    
    
    这意味着两个调用都被正确路由到各自的服务。
  • 谓词和过滤器请求

    我们在上面的例子中使用了 Path 谓词。以下是一些其他重要的谓词 -
    谓词 描述
    Cookie 谓词(输入:名称和正则表达式) 将带有“名称”的 cookie 与“正则表达式”进行比较
    Header 谓词(输入:名称和正则表达式) 将带有“名称”的标头与“正则表达式”进行比较
    Host(输入:名称和正则表达式) 将传入的“名称”与“正则表达式”进行比较
    Weight 谓词(输入:组名和权重) Weight 谓词(输入:组名和权重)
    Filters 用于在将数据发送到下游服务或将响应发送回客户端之前从请求中添加/删除数据。
    以下是一些用于添加元数据的重要过滤器。
    筛选 描述
    添加请求头过滤器(输入:头和值) 在向下游转发请求之前添加“标头”和“值”。
    添加响应头过滤器(输入:头和值) 在将请求上游转发到客户端之前,添加“标头”和“值”。
    重定向过滤器(输入:状态和 URL) 在传递给下游主机之前,添加重定向标头和 URL。
    ReWritePath(输入:正则表达式和替换) 这负责通过用输入替换替换“regexp”匹配字符串来重写路径。
  • 监控

    为了监控网关或访问各种路由、谓词等,我们可以在项目中启用执行器。为此,让我们首先更新 pom.xml 以包含执行器作为依赖项。
    
    
    <dependency>
    
          <groupId>org.springframework.boot</groupId>
    
          <artifactId>spring-boot-starter-actuator</artifactId>
    
    </dependency>
    
    
    对于监控,我们将使用一个单独的应用程序属性文件,其中包含启用执行器的标志。所以,这是它的样子 -
    
    
    spring:
    
       application:
    
          name: restaurant-gateway-service
    
       cloud:
    
          gateway:
    
             discovery:
    
                locator:
    
                   enabled: true
    
             routes:
    
                - id: customers
    
                  uri: lb://customer-service
    
                  predicates:
    
                  - Path=/customer/**
    
                - id: restaurants
    
                  uri: lb://restaurant-service
    
                  predicates:
    
                  - Path=/restaurant/**
    
    server:
    
       port: ${app_port}
    
    eureka:
    
       client:
    
          serviceURL:
    
             defaultZone: http://localhost:8900/eureka
    
    management:
    
       endpoint:
    
          gateway:
    
             enabled: true
    
       endpoints:
    
          web:
    
             exposure:
    
                include: gateway
    
    
    现在,要列出所有路由,我们可以点击:http://localhost:8084/actuator/gateway/routes
    
    
    [
    
       {
    
          "predicate": "Paths: [/customer/**], match trailing slash: true",
    
          "route_id": "customers",
    
          "filters": [],
    
          "uri": "lb://customer-service",
    
          "order": 0
    
       },
    
       {
    
          "predicate": "Paths: [/restaurant/**], match trailing slash: true",
    
          "route_id": "restaurants",
    
          "filters": [],
    
          "uri": "lb://restaurant-service",
    
          "order": 0
    
       }
    
    ]
    
    
    其他重要的监控 API -
    url 描述
    GET /actuator/gateway/routes/{id} 获取有关特定路线的信息
    POST /gateway/routes/{id_to_beassigned} 添加到网关的新路由
    DELETE /gateway/routes/{id} 从网关中删除路由
    POST /gateway/flush 删除所有缓存条目