Spring Cloud - 网关


介绍

在分布式环境中,服务需要相互通信。然而,这是服务间通信。我们还有这样的用例:域外的客户端想要访问我们的 API 服务。因此,我们可以公开可由客户端调用的所有微服务的地址,或者我们可以创建一个服务网关,将请求路由到各种微服务并响应客户端。

在这里创建网关是更好的方法。有两个主要优点 -

  • 不需要维护每个单独服务的安全性。

  • 并且,横切关注点(例如元信息的添加)可以在单个位置处理。

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

Spring Cloud Gateway – 依赖设置

让我们以我们一直在使用的餐厅为例。让我们在两个服务(即餐厅服务和客户服务)前面添加一个新服务(网关)。首先,让我们使用以下依赖项更新服务的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>

然后,使用正确的注释(即@EnableDiscoveryClient)来注释我们的Spring应用程序类。

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 服务发现来获取为特定用例提供服务的主机列表

带网关的动态路由

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

上述配置的注意事项 -

  • 我们启用了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 与“正则表达式”进行比较
标头谓词(输入:名称和正则表达式) 将标头的“名称”与“正则表达式”进行比较
主机谓词(输入:名称和正则表达式) 将传入的“名称”与“正则表达式”进行比较
权重谓词(输入:组名称和权重) 权重谓词(输入:组名称和权重)

过滤器用于在将数据发送到下游服务之前或将响应发送回客户端之前从请求中添加/删除数据。

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

筛选 描述
添加请求头过滤器(输入:头和值) 在将请求转发到下游之前添加“标头”和“值”。
添加响应标头过滤器(输入:标头和值) 在将请求上游转发到客户端之前添加“标头”和“值”。
重定向过滤器(输入:状态和 URL) 在传递到下游主机之前添加重定向标头和 URL。
ReWritePath(输入:正则表达式和替换) 它负责通过用输入替换替换“regexp”匹配字符串来重写路径。

过滤器和谓词的详尽列表位于https://cloud.spring.io/spring-cloudgateway/reference/html/#the-rewritepath-gatewayfilter-factory

监控

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

应用程序编程接口 描述
GET /执行器/网关/路由/{id} 获取有关特定路线的信息
POST /gateway/routes/{id_to_be 分配} 添加到网关的新路由
删除/网关/路线/{id} 从网关中删除路由
POST /网关/刷新 删除所有缓存条目