Spring Cloud 简明教程
Spring Cloud - Gateway
Introduction
在分布式环境中,服务需要相互通信。但是,这是服务间通信。我们也有这样的用例:我们域外的客户希望点击我们的服务以获取 API。因此,我们可以公开所有可以在客户端调用的微服务的地址,也可以创建一个服务网关,将请求路由到各个微服务,并响应客户端。
In a distributed environment, services need to communicate with each other. However, this is interservice communication. We also have use-cases where a client outside our domain wants to hit our services for the API. So, either we can expose the address of all our microservices which can be called by clients OR we can create a Service Gateway which routes the request to various microservices and responds to the clients.
创建网关在本文档中是一个更好的方法。有以下两个主要优点:
Creating a Gateway is much better approach here. There are two major advantages −
-
The security for each individual services does not need to maintained.
-
And, cross-cutting concerns, for example, addition of meta-information can be handled at a single place.
Netflix Zuul 和 Spring Cloud Gateway 是两个众所周知的云网关,用于处理此类情况。在本教程中,我们将使用 Spring Cloud Gateway。
Netflix Zuul and Spring Cloud Gateway are two well-known Cloud Gateways which are used to handle such situations. In this tutorial, we will use Spring Cloud Gateway.
Spring Cloud Gateway – Dependency Setting
让我们使用我们一直在使用的餐馆的案例。让我们在我们两个服务的前面添加一个新服务(网关),即餐馆服务和客户服务。首先,让我们使用以下依赖关系更新服务的 pom.xml :
Let us use the case of Restaurant which we have been using. Let us add a new service (gateway) in front of our two services, i.e., Restaurant services and Customer Service. First, let us update the pom.xml of the service with the following dependency −
<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。
And then, annotate our Spring application class with the correct annotation, i.e., @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 服务发现来获取托管特定用例的主机列表
We are annotating with @EnableDiscoveryClient because we want to use Eureka service discovery to get the list of hosts which are serving a particular use-case
Dynamic Routing with Gateway
Spring Cloud Gateway 有三个重要的部分。它们是:
The Spring Cloud Gateway has three important parts to it. Those are −
-
Route − These are the building blocks of the gateway which contain URL to which request is to be forwarded to and the predicates and filters that are applied on the incoming requests.
-
Predicate − These are the set of criteria which should match for the incoming requests to be forwarded to internal microservices. For example, a path predicate will forward the request only if the incoming URL contains that path.
-
Filters − These act as the place where you can modify the incoming requests before sending the requests to the internal microservices or before responding back to the client.
我们针对餐厅和客户服务编写一个用于网关的简单配置。
Let us write a simple configuration for the Gateway for our Restaurant and Customer service.
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 −
Points to note about the above configuration −
-
We have enabled the discovery.locator to ensure that the gateway can read from the Eureka server.
-
We have used Path predicated here to route the request. What this means is that any request which begins with /customer would be routed to Customer Service and for /restaurant, we will forward that request to Restaurant Service.
现在让我们设置网关服务之前需要的其他服务——
Now let us setup other services prior to the Gateway service −
-
Start the Eureka Server
-
Start the Customer Service
-
Start the Restaurant Service
现在,让我们编译并执行网关项目。我们将为此使用以下命令——
Now, let us compile and execute the Gateway project. We will use the following command for the same −
java -Dapp_port=8084 -jar .\target\spring-cloud-gateway-1.0.jar
完成后,我们的网关便已准备好好在端口 8084 上进行测试。让我们首先访问 [role="bare"] [role="bare"]http://localhost:8084/customer/1 ,我们看到请求正确路由到客户服务,并且我们获得以下输出——
Once this is done, we have our Gateway ready to be tested on port 8084. Let’s first hit [role="bare"]http://localhost:8084/customer/1 and we see the request is correctly routed to Customer Service and we get the following output −
{
"id": 1,
"name": "Jane",
"city": "DC"
}
现在,访问我们的餐厅 API,即 [role="bare"] [role="bare"]http://localhost:8084/restaurant/customer/1 ,我们获得以下输出——
And now, hit our restaurant API, i.e., [role="bare"]http://localhost:8084/restaurant/customer/1 and we get the following output −
[
{
"id": 1,
"name": "Pandas",
"city": "DC"
},
{
"id": 3,
"name": "Little Italy",
"city": "DC"
}
]
这意味着两个调用都正确路由到各个服务。
This means that both the calls were correctly routed to the respective services.
Predicates & Filters Request
我们在上述示例中使用了路径谓词。以下是其他几个重要谓词——
We had used Path predicate in our above example. Here are a few other important predicates −
Predicate |
Description |
Cookie predicate (input: name and regex) |
Compares the cookie with the ‘name’ to the ‘regexp’ |
Header predicate (input: name and regex) |
Compares the header with the ‘name’ to the ‘regexp’ |
Host predicate (input: name and regex) |
Compares the ‘name’ of the incoming to the ‘regexp’ |
Weight Predicate (input: Group name and the weight) |
Weight Predicate (input: Group name and the weight) |
Filters 用于在向下游服务发送数据或向客户端发送响应之前,向请求添加/删除数据。
Filters are used to add/remove data from the request before sending the data to the downstream service or before sending the response back to the client.
以下是添加元数据的一些重要过滤器。
Following are a few important filters for adding metadata.
Filter |
Description |
Add request header filter (input: header and the value) |
Add a ‘header’ and the ‘value’ before forwarding the request downstream. |
Add response header filter (input: header and the value) |
Add a ‘header’ and the ‘value’ before forwarding the request upstream that is to the client. |
Redirect filter (input: status and URL) |
Adds a redirect header along with the URL before passing over o the downstream host. |
ReWritePath (input: regexp and replacement) |
This is responsible for rewriting the path by replacing the ‘regexp’ matched string with the input replacement. |
过滤和谓词的详尽列表存在于 https://cloud.spring.io/spring-cloudgateway/reference/html/#the-rewritepath-gatewayfilter-factory
The exhaustive list for filters and predicates is present at https://cloud.spring.io/spring-cloudgateway/reference/html/#the-rewritepath-gatewayfilter-factory
Monitoring
为监视网关或访问各种路由、谓词等,我们可以在项目中启用执行器。为此,让我们首先更新 pom.xml,将执行器作为依赖项包含在内。
For monitoring of the Gateway or for accessing various routes, predicates, etc., we can enable the actuator in the project. For doing that, let us first update the pom.xml to contain the actuator as a dependency.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
对于监控,我们将使用一个单独的应用程序属性文件,其中将包含用于启用执行器的标志。因此,以下是它的样子 −
For monitoring, we will use a separate application property file which would contain flags to enable the actuator. So, here is how it would look like −
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
Now, to list all the routes, we can hit: [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 −
Other important APIs for monitoring −
API |
Description |
GET /actuator/gateway/routes/{id} |
Get information about a particular route |
POST /gateway/routes/{id_to_be assigned} |
Add a new route to the Gateway |
DELETE /gateway/routes/{id} |
Remove the route from Gateway |
POST /gateway/refresh |
Remove all the cache entries |