Spring Cloud - 网关
简介
在分布式环境中,服务需要彼此通信。但是,这是服务间通信。我们也有这样的用例:域外的客户端需要访问我们的服务的 API。因此,我们可以公开所有微服务地址供客户端调用,或者创建一个服务网关来将请求路由到各种微服务并响应客户端。
在这里,创建网关是一种更好的方法。它有两个主要优点:
无需维护每个单独服务的安全性。
并且,可以集中处理横切关注点,例如添加元信息。
Netflix Zuul 和 Spring 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: https://127.0.0.1:8900/eureka
关于上述配置的几点说明:
我们启用了discovery.locator 以确保网关可以从 Eureka 服务器读取。
我们在这里使用了 Path 断言来路由请求。这意味着任何以 /customer 开头的请求都将路由到客户服务,对于 /restaurant,我们将该请求转发到餐厅服务。
现在,让我们在网关服务之前设置其他服务:
启动 Eureka 服务器
启动客户服务
启动餐厅服务
现在,让我们编译并执行网关项目。我们将使用以下命令:
java -Dapp_port=8084 -jar .\target\spring-cloud-gateway-1.0.jar
完成后,我们的网关准备好在 8084 端口上进行测试。让我们首先访问 https://127.0.0.1:8084/customer/1,我们会看到请求被正确路由到客户服务,并且我们得到以下输出:
{ "id": 1, "name": "Jane", "city": "DC" }
现在,访问我们的餐厅 API,即 https://127.0.0.1:8084/restaurant/customer/1,我们得到以下输出:
[ { "id": 1, "name": "Pandas", "city": "DC" }, { "id": 3, "name": "Little Italy", "city": "DC" } ]
这意味着两个调用都已正确路由到各自的服务。
断言和过滤器请求
我们在上面的示例中使用了 Path 断言。以下是一些其他重要的断言:
断言 | 描述 |
---|---|
Cookie 断言(输入:名称和正则表达式) | 将 Cookie 的“名称”与“正则表达式”进行比较 |
Header 断言(输入:名称和正则表达式) | 将 Header 的“名称”与“正则表达式”进行比较 |
Host 断言(输入:名称和正则表达式) | 将传入的“名称”与“正则表达式”进行比较 |
权重断言(输入:组名和权重) | 权重断言(输入:组名和权重) |
过滤器 用于在将数据发送到下游服务之前或在将响应发送回客户端之前,向请求添加/删除数据。
以下是一些用于添加元数据的重要的过滤器。
过滤器 | 描述 |
---|---|
添加请求头过滤器(输入:头和值) | 在下游转发请求之前添加“头”和“值”。 |
添加响应头过滤器(输入:头和值) | 在上游(即客户端)转发请求之前添加“头”和“值”。 |
重定向过滤器(输入:状态和 URL) | 在传递到下游主机之前,添加包含 URL 的重定向头。 |
ReWritePath(输入:正则表达式和替换) | 负责通过将匹配的“正则表达式”字符串替换为输入替换来重写路径。 |
过滤器和断言的详尽列表位于 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: https://127.0.0.1:8900/eureka management: endpoint: gateway: enabled: true endpoints: web: exposure: include: gateway
现在,要列出所有路由,我们可以访问:https://127.0.0.1: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 | 描述 |
---|---|
GET /actuator/gateway/routes/{id} | 获取有关特定路由的信息 |
POST /gateway/routes/{id_to_be assigned} | 向网关添加新路由 |
DELETE /gateway/routes/{id} | 从网关中删除路由 |
POST /gateway/refresh | 删除所有缓存条目 |