javascript
Spring Boot微服务API网关
為什么我們需要API網關?(Why do we need API Gateway?)
To understand this pattern we must delve into the real life problems, in the microservices world. We will continue with the example of our e-commerce system. In the previous exercise, we already built Product Catalog Service, which is responsible to manage product lifecycle through — create, update, delete and get operations. Lets go through some common scenarios, you might come across, while developing the microservices.
要了解這種模式,我們必須深入研究微服務世界中的現實生活中的問題。 我們將繼續以電子商務系統為例。 在上一個練習中,我們已經構建了產品目錄服務,該產品目錄服務負責通過創建,更新,刪除和獲取操作來管理產品生命周期。 在開發微服務時,讓我們經歷一些常見的場景,您可能會遇到。
方案1-服務的多個版本 (Scenario 1 — Multiple Versions of Service)
Our Product Catalog Service is updated with the new changes, but the updated service is not compatible with the mobile client.
我們的產品目錄服務已通過新更改進行了更新,但是更新的服務與移動客戶端不兼容。
Though we cannot achieve the service update completely, we can optimize it by running multiple versions in parallel. Our mobile client will continue using the V1 while other clients will move to V2.
盡管我們無法完全實現服務更新,但是我們可以通過并行運行多個版本來對其進行優化。 我們的移動客戶端將繼續使用V1,而其他客戶端將移至V2。
方案2-限制訪問 (Scenario 2 — Restricted Access)
Our Product Catalog Service provides apis to both read and write the catalog data.
我們的產品目錄服務提供了用于讀取和寫入目錄數據的api。
Our security team suggests to limit the access of write apis — add, update and delete, from the vendor portal only — vendor.test-gateway-store.com.
我們的安全團隊建議限制對寫入api的訪問-僅可從供應商門戶( vendor.test-gateway-store.com)添加,更新和刪除。
Rest of the clients, like e-commerce portal, can only access get product api from Product Catalog Service.
其他客戶(例如電子商務門戶)只能從Product Catalog Service訪問get product api 。
方案3-監視Api性能 (Scenario 3 — Monitoring Api Performance)
Lot of customers are complaining delays while getting the product details. We must monitor the performance of “get product details” api to assess the severity and plan out the next steps.
許多客戶抱怨獲得產品詳細信息時延誤。 我們必須監視“獲取產品詳細信息” api的性能,以評估嚴重性并計劃下一步。
方案4-更新響應標頭 (Scenario 4 — Updating Response Header)
We received the performance statistics of Product Catalog Service. Get product details api is getting hit too many times. This is not needed as the product details are not updated every minute.
我們收到了產品目錄服務的性能統計數據。 獲取產品詳細信息api被擊中太多次了。 不需要此操作,因為產品詳細信息不會每分鐘更新一次。
We can avoid the unnecessary hits by introducing Cache-Control header attribute in the response of get product details api.
我們可以通過在獲取產品詳細信息api的響應中引入Cache-Control標頭屬性來避免不必要的點擊。
The above discussed scenarios typically fall into the category of cross cutting concerns and must be dealt separately . This will increase the maintainability and agility of overall system. Also if the changes are done in code, its going to create longer delivery timelines. The API Gateway pattern provides a cleaner approach to resolve such issues.
上面討論的場景通常屬于交叉關注的類別,必須單獨處理。 這將增加整個系統的可維護性和敏捷性。 同樣,如果更改是在代碼中完成的,則將創建更長的交付時間表。 API網關模式 提供了一種更清潔的方法來解決此類問題。
API網關如何工作? (How API Gateway Works?)
The API gateway takes all the api calls, from the clients and route them to appropriate microservice(s) with request routing, composition, and protocol translation.
API網關從客戶端接收所有api調用,并將它們路由到具有請求路由,組合和協議轉換的適當微服務。
API Gateway — An IllustrationAPI網關—插圖Exactly what the API gateway does will vary from one implementation to another. Some common functions include routing, rate limiting, billing, monitoring, authentication, api composition, policies, alerts, and security.
確切地說, API網關所做的工作因一個實現而異。 一些常用功能包括路由,速率限制,計費,監視,身份驗證,API組成,策略,警報和安全性。
We will be implementing the gateway pattern to solve the problems, we discussed above. These sample implementations are primarily based on Spring Cloud Gateway. This library is the preferred gateway implementation provided by Spring Cloud. Its built with Spring 5, Spring Boot 2 and Project Reactor.
我們將實現上面討論的網關模式來解決問題。 這些示例實現主要基于Spring Cloud Gateway。 該庫是Spring Cloud提供的首選網關實現。 它使用Spring 5,Spring Boot 2和Project Reactor構建。
Spring Cloud Gateway的核心功能 (The core functions of Spring Cloud Gateway)
Spring Cloud Gateway aims to provide a simple, yet effective way to route to APIs and provide cross cutting concerns to them such as: security, monitoring/metrics, and resiliency. The framework is based on three core components — Routes, Predicates and Filters.
Spring Cloud Gateway旨在提供一種簡單而有效的方法來路由到API,并為它們提供跨領域的關注點,例如:安全性,監視/度量和彈性。 該框架基于三個核心組件-路由,謂詞和過濾器。
路線 (Routes)
This is the primary component consisting of ID, Destination Uri, Predicates and Filters.
這是主要組件,由ID,Destination Uri,Predicates和Filters組成。
謂詞 (Predicates)
This is more like a condition to match the route. This is done based on the HTTP request, headers, parameters, path, cookie and other request criteria.
這更像是匹配路線的條件。 這是根據HTTP請求,標頭,參數,路徑,cookie和其他請求條件完成的。
篩選器 (Filters)
They are the plugins to update the request or response. They function similar to the servlet filters with the pre and post variations. You can use it for multiple purpose including “adding a request parameter”, “adding a response header”, “monitoring”, and many other utilities.
它們是用于更新請求或響應的插件。 它們的功能與servlet過濾器類似,但具有前后變化。 您可以將其用于多種用途,包括“添加請求參數”,“添加響應頭”,“監視”以及許多其他實用程序。
We will see the examples for each of these aspects through the sample implementations in the next section.
在下一節中,我們將通過示例實現來查看這些方面的示例。
實施Api網關 (Implementing Api Gateway)
In this section, we will implement our Api Gateway and build the solutions mapped to the scenarios discussed earlier.
在本節中,我們將實現Api網關并構建映射到前面討論的方案的解決方案。
方案1-服務的多個版本。 (Scenario 1 — Multiple versions of a service.)
As discussed earlier, we will have two version of our Product Catalog Service — V1 & V2. Lets create Product Catalog Service based on Spring Boot as explained in our very first series — Developing First Service. Assuming you are already aware of creating a Spring Boot based service, we will work on updating the Product Catalog Service.
如前所述,我們將提供兩個版本的產品目錄服務-V1和V2。 讓我們 如第一個系列“開發第一服務”中所述,基于Spring Boot創建產品目錄服務。 假設您已經知道創建基于Spring Boot的服務,我們將致力于更新Product Catalog Service 。
Lets introduce a new method — getVersion in this service, which does a simple job to display the service version.
讓我們在該服務中引入一個新方法getVersion ,它可以很簡單地顯示服務版本。
@RestControllerpublic class ProductCatalogService {
... @GetMapping("/product/version")
public String getVersionInfo(){
return "Version - V1";
}}
Copy the whole project to create a new version of our Product Catalog Service. Implement the getVersion method similar to the one above. The only difference is the version name — V2.
復制整個項目以創建我們產品目錄服務的新版本。 實現類似于上述方法的getVersion方法。 唯一的區別是版本名稱-V2。
@RestControllerpublic class ProductCatalogService {
... @GetMapping("/product/version")
public String getVersionInfo(){
return "Version - V2"; }}
Update the respective application properties to avoid the port conflicts. We will be running Version 1 on port 8081 and Version 2 on port 8082.
更新相應的應用程序屬性,以避免端口沖突。 我們將在端口8081上運行版本1,并在端口8082上運行版本2。
server.port=8081 #8081 for V1 and #8082 for V2Run both the service versions with the maven command mvn spring-boot:run , in the respective directories. You should be able to view the specific versions by visiting http://localhost:8081/product/version or http://localhost:8082/product/version urls.
使用maven命令mvn spring-boot:run在相應目錄中運行兩個服務版本。 您應該能夠通過訪問http://localhost:8081/product/version或http://localhost:8082/product/version URL來查看特定版本。
Its time to create our API Gateway server. Lets go to our favorite store to create Spring Boot application — The Spring Initializer. Add the Spring Cloud Gateway dependency.
是時候創建我們的API網關服務器了。 讓我們去我們最喜歡的商店創建Spring Boot應用程序-Spring Initializer 。 添加Spring Cloud Gateway依賴項。
Generate, download and unpack the archive to your local system. Open the project with your favorite code editor. We will be creating src/main/resources/application.yml file for the gateway server configuration.
生成,下載歸檔文件并將其解壓縮到本地系統。 使用您喜歡的代碼編輯器打開項目。 我們將為網關服務器配置創建src/main/resources/application.yml文件。
server:port: 9090
spring:
cloud:
gateway:
routes:
- id: product_service_v1
uri: 'http://localhost:8081'
predicates:
- Path=/product/**
- Query=src,mobile
- id: product_service_v2
uri: 'http://localhost:8082'
predicates:
- Path=/product/**
We are defining two routes here — product_service_v2 and product_service_v1 . The first version can only be accessed by Mobile devices. We are using two predicates for product_service_v1 to achieve this —
我們在此處定義兩條路由product_service_v2和product_service_v1 。 第一個版本只能由移動設備訪問。 我們使用product_service_v1兩個謂詞來實現這一目標-
- Path (/product/**) — This will match the path pattern containing ‘/product’ with any suffix. - 路徑(/ product / **)-這將匹配包含“ / product”和任何后綴的路徑模式。 
- Query (src,mobile) — This will match the query parameter in the path if src parameter is available and has a value mobile - 查詢(src,mobile)-如果src參數可用并且值為mobile ,則它將與路徑中的查詢參數匹配 
If both the conditions meet, the request will be forwarded to http://localhost:8081 as specified against uri attribute. If only the path matches, request will be forwarded to http://localhost:8082 .
如果兩個條件都滿足,則將根據uri屬性將請求轉發到http://localhost:8081 。 如果僅路徑匹配,則請求將轉發到http://localhost:8082 。
Lets start our gateway server by running mvn spring-boot:run and visit following urls
讓我們通過運行mvn spring-boot:run啟動我們的網關服務器mvn spring-boot:run并訪問以下URL
- http://localhost:9090/product/version?src=mobile — You will see the message — “Version V1” - http://localhost:9090/product/version?src=mobile —您將看到消息— “ Version V1” 
- http://localhost:9090/product/version —You will see the message — “Version V2” - http://localhost:9090/product/version —您將看到消息— “ Version V2” 
Congratulations. You just completed the first sample routing for our Api Gateway. We used predicates to route the requests to different versions of a service.
恭喜你您剛剛完成了Api網關的第一個示例路由。 我們使用謂詞將請求路由到服務的不同版本。
方案2-限制訪問 (Scenario 2- Restricted Access)
As discussed earlier, we need to restrict the access of our write operations including create, update and delete apis of Product Catalog Service. We will do this by updating our route definitions.
如前所述,我們需要限制對寫入操作的訪問,包括創建,更新和刪除Product Catalog Service的api。 我們將通過更新路線定義來做到這一點。
But this time we will to do it in a different way. Spring cloud gateway supports route definition in two ways — configuration files and code. We already used the first option, now we will use the second. Update your GatewayServerApplication.java , the auto generated java file in our gateway server, with the highlighted code.
但是這次我們將以不同的方式來做。 Spring Cloud Gateway通過兩種方式支持路由定義-配置文件和代碼。 我們已經使用了第一個選項,現在我們將使用第二個選項。 使用突出顯示的代碼更新您的GatewayServerApplication.java中自動生成的Java文件GatewayServerApplication.java 。
@SpringBootApplicationpublic class GatewayServerApplication { public static void main(String[] args) {
SpringApplication.run(GatewayServerApplication.class, args);
} @Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("path_route", r -> r.path("/product").and().method("POST", "PUT", "DELETE").and().host("vendor.test-gateway-store.com")
.uri("http://localhost:8081"))
.route("path_route", r -> r.path("/product/**").and().method("GET")
.uri("http://localhost:8082"))
.build();
}}
With the customRouteLocator method, we are again defining two routes. The first route definition says — if a request is received with the path “/product” and the method type is either POST, PUT or DELETE and the host is vendor.test-gateway-store.com then allow the request to be forwarded to http://localhost:8081
使用customRouteLocator 方法,我們再次定義了兩條路線。 第一個路由定義是-如果接收到帶有路徑“ / product”的請求,并且方法類型為POST,PUT或DELETE ,且主機為vendor.test-gateway-store.com,則允許將請求轉發至http://localhost:8081
The second route takes care of all the get requests with the pattern /product/** , and forwards them to http://localhost:8082
第二條路由使用/product/**模式處理所有get請求,并將它們轉發到http://localhost:8082
If you run your post requests from your local machine, it will fail. If you want them to pass update the host value in the first route as “localhost*”. The get requests will pass for all the different sources.
如果您從本地計算機運行發帖請求,它將失敗。 如果希望它們通過,請將第一條路由中的主機值更新為“ localhost *” 。 獲取請求將傳遞給所有不同的源。
Great! We solved another major issue with the minimal configuration. Two more to go!
大! 我們用最小的配置解決了另一個主要問題。 還有兩個!
方案3-監視Apis (Scenario 3 — Monitoring Apis)
This is relatively simpler. To enable gateway metrics, add spring-boot-starter-actuator as a project dependency in our gateway sever application. Gateway Metrics Filter is a global filter and does not need any route configuration. The global filters are special filters that are conditionally applied to all the routes. Lets update the pom.xml to include the actuator dependency —
這是相對簡單的。 要啟用網關指標,請在我們的網關服務器應用程序中將spring-boot-starter-actuator添加為項目依賴項。 網關度量標準篩選器是全局篩選器,不需要任何路由配置。 全局過濾器是特殊過濾器,有條件地應用于所有路由。 讓我們更新pom.xml以包括執行器依賴項-
<project>... <dependencies>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency></dependencies></project>
Enable the specific actuator views, in src/main/resources/application.properties . This will enable us to view the metrics through browser.
在src/main/resources/application.properties啟用特定的執行器視圖。 這將使我們能夠通過瀏覽器查看指標。
management.endpoints.web.exposure.include=gateway,metricsStart the gateway server and access the metrics at http://localhost:9090/actuator/metrics/gateway.requests . You can view a response similar to the one below.
啟動網關服務器,并訪問http://localhost:9090/actuator/metrics/gateway.requests 。 您可以查看與以下響應類似的響應。
{"name": "gateway.requests",
"description": null,
"baseUnit": "seconds",
"measurements": [
{
"statistic": "COUNT",
"value": 4
},
{
"statistic": "TOTAL_TIME",
"value": 1.754685765
},
{
"statistic": "MAX",
"value": 0.086543555
}
],
"availableTags": [
{
"tag": "routeUri",
"values": [
"http://localhost:8082",
"http://localhost:8081"
]
},...
]
}
The above response provides valuable insights including the count of requests, total time taken and maximum time taken for the api response. The above figures reflect the numbers aggregated across all the requests. You can check the specific figures based on routeId, routeUri, outcome, status, httpStatusCode and httpMethod, which are available as filter tags. So if you want to monitor the api on http://localhost:8082 , we can access it through
上面的響應提供了有價值的見解,包括請求的計數,花費的總時間以及api響應的最長時間。 上面的數字反映了所有請求中匯總的數字。 您可以根據routeId,routeUri,結果,狀態,httpStatusCode和httpMethod(可作為過濾器標簽使用)檢查特定數字。 因此,如果您想監視http://localhost:8082上的api,我們可以通過訪問它
http://localhost:9090/actuator/metrics/gateway.requests?tag=routeUri:http://localhost:8082The above metrics can be easily integrated with Prometheus to create a Grafana dashboard.
可以輕松地將上述指標與Prometheus集成以創建Grafana儀表板。
方案4-更新響應標頭 (Scenario 4 — Updating Response Header)
So our monitoring results indicate that the get product details api throughput is on compromising side. We will use the basic caching mechanism to improve its performance. We will take help of cache-control response header to limit the hits on the server side. Product details or list are not updated so frequently.
因此,我們的監控結果表明,獲取產品詳細信息的api吞吐量處于不利的一面。 我們將使用基本的緩存機制來提高其性能。 我們將利用cache-control響應標頭來限制服務器端的點擊。 產品詳細信息或列表更新不是那么頻繁。
For our test purpose we will add max-age attribute to it with value of 5 mins. This means the client of this api (get product details) will keep the cache of api results for 5 mins. If the user tries to get the product details with in this period, the cached result will be returned.
出于測試目的,我們將為其添加max-age屬性,其值為5分鐘。 這意味著此api的客戶端(獲取產品詳細信息)會將api結果的緩存保留5分鐘。 如果用戶在此期間嘗試獲取產品詳細信息,則將返回緩存的結果。
Lets update our GatewayServerApplication.java
讓我們更新我們的GatewayServerApplication.java
@Beanpublic RouteLocator customRouteLocator(RouteLocatorBuilder builder)
{
return builder.routes()
.route("path_route", r -> r.path("/product").and().method("POST", "PUT", "DELETE").and().host("localhost*")
.uri("http://localhost:8081"))
.route("path_route", r -> r.path("/product/**").and().method("GET")
.filters(f -> f.addResponseHeader("Cache-Control", "max-age=300"))
.uri("http://localhost:8082"))
.build();}
We added the required response header with the help of a pre defined filter — Add Response Header filter.
我們在預定義的過濾器(添加響應頭過濾器)的幫助下添加了所需的響應頭。
Restart the gateway server and try to get the product list. Inspect its response headers and you will find the cache-control header we introduced just now. If you try to add a product now, and refresh, all with in 5 mins, your list will not be updated on the browser side.
重新啟動網關服務器,然后嘗試獲取產品列表。 檢查其響應標頭,您將找到我們剛才介紹的緩存控制標頭。 如果您嘗試在5分鐘內立即添加產品并刷新所有內容,則列表不會在瀏覽器端更新。
Bravo! we finished all the scenarios in less than 10 mins.
太棒了! 我們在不到10分鐘的時間內完成了所有場景。
學習永無止境 (Learning never stops)
We are able to implement our basic API Gateway server based on Spring Cloud Gateway. The complete source code of the examples, is available at Github. We tried to get a practical insight into the API Gateway pattern but we just scratched the surface, in terms of features.
我們能夠實現基于Spring Cloud Gateway的基本API網關服務器。 示例的完整源代碼可在Github上獲得。 我們嘗試了 以獲得對API網關模式的實用見解,但我們只是從功能上進行了介紹。
We explored few predicates like path, method and host. But the Spring Cloud Gateway provides many more built-in route predicate factories including After/Before/Between DateTime, Cookie, Header, Host, Method, Path, Query, Remote Address and Weight.
我們探索了一些謂詞,例如路徑,方法和宿主。 但是Spring Cloud Gateway提供了更多內置的路由謂詞工廠,包括DateTime之后/ Before / Between之間,Cookie,標題,主機,方法,路徑,查詢,遠程地址和權重。
We explored the Add Response filter to implement the cache strategy. Similar to the built-in predicates, there are many other built-in filters too, including Add Request, Add Response, Circuit Breaker, Hystrix, Fallback, Map Request, Prefix Path, Preserve Host, Request Rate Limiter, etc. We can add a custom filter too if the already available set does not suffice the needs.
我們探索了添加響應過濾器以實現緩存策略。 與內置謂詞類似,也有很多其他內置過濾器,包括添加請求,添加響應,斷路器,Hystrix,回退,映射請求,前綴路徑,保留主機,請求速率限制器等。 如果已經可用的集合不能滿足需要,我們也可以添加自定義過濾器。
The library provides options to cater advance routing needs with Cors Configuration. We already discussed monitoring api performance but the actuator api provides rich set of monitoring options. Do check out the Spring Cloud Gateway documentation to further upgrade your skills with this technology.
該庫提供了一些選項,以通過Cors Configuration滿足高級路由需求。 我們已經討論了監視api的性能,但是執行器api提供了豐富的監視選項集。 請查看Spring Cloud Gateway文檔,以進一步升級使用此技術的技能。
You can browse:1. Next Exercise - Implementing Circuit Breaker 2. Prev Exercise - Implementing Distributed Tracing3. Complete Series - Spring Boot Microservices - Learning through Examples翻譯自: https://medium.com/an-idea/spring-boot-microservices-api-gateway-e9dbcd4bb754
總結
以上是生活随笔為你收集整理的Spring Boot微服务API网关的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: The Canonical List o
- 下一篇: 返回 代码: E_INVALIDARG
