Spring Cloud 简明教程

Spring Cloud - Gateway

Introduction

在分布式环境中,服务需要相互通信。但是,这是服务间通信。我们也有这样的用例:我们域外的客户希望点击我们的服务以获取 API。因此,我们可以公开所有可以在客户端调用的微服务的地址,也可以创建一个服务网关,将请求路由到各个微服务,并响应客户端。

创建网关在本文档中是一个更好的方法。有以下两个主要优点:

  1. 无需维护各个服务的安全性。

  2. 而且,跨领域问题,例如添加元信息,可以在一个地方进行处理。

Netflix ZuulSpring Cloud Gateway 是两个众所周知的云网关,用于处理此类情况。在本教程中,我们将使用 Spring Cloud Gateway。

Spring Cloud Gateway – Dependency Setting

让我们使用我们一直在使用的餐馆的案例。让我们在我们两个服务的前面添加一个新服务(网关),即餐馆服务和客户服务。首先,让我们使用以下依赖关系更新服务的 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.tutorialspoint;
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 服务发现来获取托管特定用例的主机列表

Dynamic Routing with Gateway

Spring Cloud Gateway 有三个重要的部分。它们是:

  1. Route − 这些是网关的构建块,其中包含要将请求转发到的 URL 以及应用于传入请求的谓词和过滤器。

  2. Predicate − 这是一个标准集,该标准集应与要转发到内部微服务的传入请求匹配。例如,路径谓词仅在传入 URL 包含该路径时才会转发请求。

  3. Filters − 它们充当了位置,你可以在向内部微服务发送请求或向客户端进行回复之前在此修改传入请求。

我们针对餐厅和客户服务编写一个用于网关的简单配置。

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 −

  1. 我们启用了 discovery.locator 以确保网关能够从 Eureka 服务器读取。

  2. 我们在此处使用了基于路径的谓词来路由请求。这意味着以 / customer 开头的任何请求都将路由到客户服务,而对于 / restaurant ,我们将该请求转发给餐厅服务。

现在让我们设置网关服务之前需要的其他服务——

  1. Start the Eureka Server

  2. Start the Customer Service

  3. Start the Restaurant Service

现在,让我们编译并执行网关项目。我们将为此使用以下命令——

java -Dapp_port=8084 -jar .\target\spring-cloud-gateway-1.0.jar

完成后,我们的网关便已准备好好在端口 8084 上进行测试。让我们首先访问 [role="bare"] [role="bare"]http://localhost:8084/customer/1 ,我们看到请求正确路由到客户服务,并且我们获得以下输出——

{
   "id": 1,
   "name": "Jane",
   "city": "DC"
}

现在,访问我们的餐厅 API,即 [role="bare"] [role="bare"]http://localhost:8084/restaurant/customer/1 ,我们获得以下输出——

[
   {
      "id": 1,
      "name": "Pandas",
      "city": "DC"
   },
   {
      "id": 3,
      "name": "Little Italy",
      "city": "DC"
   }
]

这意味着两个调用都正确路由到各个服务。

Predicates & Filters Request

我们在上述示例中使用了路径谓词。以下是其他几个重要谓词——

Predicate

Description

Cookie 谓词(输入:名称和正则表达式)

将 Cookie 中的“名称”与“正则表达式”进行比较

Header 谓词(输入:名称和正则表达式)

将 Header 中的“名称”与“正则表达式”进行比较

Host 谓词(输入:名称和正则表达式)

将传入请求的“名称”与“正则表达式”进行比较

权重谓词(输入:组名称和权重)

权重谓词(输入:组名称和权重)

Filters 用于在向下游服务发送数据或向客户端发送响应之前,向请求添加/删除数据。

以下是添加元数据的一些重要过滤器。

Filter

Description

添加请求标头过滤器(输入:标头和值)

在将请求向下游转发之前添加一个“标头”和“值”。

添加响应标头过滤器(输入:标头和值)

在将请求向上游(即客户端)转发之前添加一个“标头”和“值”。

重定向过滤器(输入:状态和 URL)

在传递到下游主机之前,添加一个重定向标头以及 URL。

ReWritePath(输入:regexp 和替换)

此过滤器负责通过使用输入替换替换与“regexp”匹配的字符串来重写路径。

Monitoring

为监视网关或访问各种路由、谓词等,我们可以在项目中启用执行器。为此,让我们首先更新 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

现在,要列出所有路由,我们可以点击: [role="bare"] [role="bare"]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 −

API

Description

GET /actuator/gateway/routes/{id}

获取有关特定路由的信息

POST /gateway/routes/{id_to_be assigned}

将新路由添加到网关

DELETE /gateway/routes/{id}

从网关中移除路由

POST /gateway/refresh

移除所有缓存条目