使用 Node.js 搭建一個 API 閘道器

牧云云發表於2017-08-15

使用 Node.js 搭建一個 API 閘道器

外部客戶端訪問微服務架構中的服務時,服務端會對認證和傳輸有一些常見的要求。API 閘道器提供共享層來處理服務協議之間的差異,並滿足特定客戶端(如桌面瀏覽器、移動裝置和老系統)的要求。

微服務和消費者

微服務是面向服務的架構,團隊可以獨立設計、開發和釋出應用程式。它允許在系統各個層面上的技術多樣性,團隊可以在給定的技術難題中使用最佳語言、資料庫、協議和傳輸層,從而受益。例如,一個團隊可以使用 HTTP REST 上的 JSON,而另一個團隊可以使用 HTTP/2 上的 gRPC 或 RabbitMQ 等訊息代理。

在某些情況下使用不同的資料序列化和協議可能是強大的,但要使用我們的產品的客戶可能有不同的需求。該問題也可能發生在具有同質技術棧的系統中,因為客戶可以從桌面瀏覽器通過移動裝置和遊戲機到遺留系統。一個客戶可能期望 XML 格式,而另一個客戶可能希望 JSON 。在許多情況下,您需要同時支援它們。

當客戶想要使用您的微服務時,您可以面對的另一個挑戰來自於通用的共享邏輯(如身份驗證),因為您不想在所有服務中重新實現相同的事情。

總結:我們不想在我們的微服務架構中實現我們的內部服務,以支援多個客戶端並可以重複使用相同的邏輯。這就是 API 閘道器出現的原因,其作為共享層來處理服務協議之間的差異並滿足特定客戶端的要求。

什麼是 API 閘道器?

API 閘道器是微服務架構中的一種服務,它為客戶端提供共享層和 API,以便與內部服務進行通訊。API 閘道器可以進行路由請求、轉換協議、聚合資料以及實現共享邏輯,如認證和速率限制器。

您可以將 API 閘道器視為我們的微服務世界的入口點

我們的系統可以有一個或多個 API 閘道器,具體取決於客戶的需求。例如,我們可以為桌面瀏覽器、移動應用程式和公共 API 提供單獨的閘道器。

API Gateway
API Gateway

API 閘道器作為微服務的切入點

Node.js 用於前端團隊的 API 閘道器

由於 API 閘道器為客戶端應用程式(如瀏覽器)提供了功能,它可以由負責開發前端應用程式的團隊實施和管理。

這也意味著用哪種語言實現 API Gateway 應由負責特定客戶的團隊選擇。由於 JavaScript 是開發瀏覽器應用程式的主要語言,即使您的微服務架構以不同的語言開發,Node.js 也可以成為實現 API 閘道器的絕佳選擇。

Netflix 成功地使用 Node.js API 閘道器及其 Java 後端來支援廣泛的客戶端 - 瞭解更多關於它們的方法閱讀 The "Paved Road" PaaS for Microservices at Netflix 這篇文章

Netflix 處理不同客戶端的方法, 資源

API 閘道器功能

我們之前討論過,可以將通用共享邏輯放入您的 API 閘道器,本節將介紹最常見的閘道器職責。

路由和版本控制

我們將 API 閘道器定義為您的微服務的入口點。在您的閘道器服務中,您可以指定從客戶端路由到特定服務的路由請求。您甚至可以通過路由處理版本或更改後端介面,而公開的介面可以保持不變。您還可以在您的 API 閘道器中定義與多個服務配合的新端點。

API Gateway - Entry point
API Gateway - Entry point

API 閘道器作為微服務入口點

閘道器設計的升級

API 閘道器方法也可以幫助您分解您的整體應用程式。在大多數情況下,在微服務端重構一個系統不是一個好主意也是不可能的,因為我們需要在重構期間為業務傳送新的以及原有的功能。

在這種情況下,我們可以將代理或 API 閘道器置於我們的整體應用程式之前,將新功能作為微服務實現,並將新端點路由到新服務,同時通過原有的路由服務舊端點。這樣以後,我們也可以通過將原有功能轉變為新服務來分解整體。

隨著閘道器設計的升級,我們可以實現整體架構到微型服務的平滑過渡

API Gateway - Evolutionary design
API Gateway - Evolutionary design

API 閘道器設計的升級

認證

大多數微服務基礎設施需要進行身份驗證。將共享邏輯(如身份驗證)新增到 API 閘道器可以幫助您保持您的服務的體積變小以及可以集中管理域

在微服務架構中,您可以通過網路配置將您的服務保護在 DMZ (保護區)中,並通過 API 閘道器向客戶公開。該閘道器還可以處理多個身份驗證方法。例如,您可以同時支援基於 cookietoken 的身份驗證。

API Gateway - Authentication
API Gateway - Authentication

具有認證功能的 API 閘道器

資料彙總

在微服務架構中,可能客戶端所需要的資料的聚合級別不同,比如對在各種微服務中產生的非規範化資料實體。在這種情況下,我們可以使用我們的 API 閘道器來解決這些依賴關係並從多個服務收集資料。

在下圖中,您可以看到 API 閘道器如何將使用者和信用資訊作為一個資料返回給客戶端。請注意,這些資料由不同的微服務所擁有和管理。

API Gateway - Data aggregation
API Gateway - Data aggregation

序列化格式轉換

我們需要支援客戶端不同的資料序列化格式這樣子的需求可能會發生。

想象一下我們的微服務使用 JSON 的情況,但我們的客戶只能使用 XML APIs。在這種情況下,我們可以在 API 閘道器中把 JSON 轉換為 XML,而不是在所有的微伺服器中分別進行實現。

API Gateway - Data serialization format transformation
API Gateway - Data serialization format transformation

協議轉換

微服務架構允許多通道協議傳輸從而獲取多種技術的優勢。然而,大多數客戶端只支援一個協議。在這種情況下,我們需要轉換客戶端的服務協議。

API 閘道器還可以處理客戶端和微伺服器之間的協議轉換。

在下一張圖片中,您可以看到客戶端希望通過 HTTP REST 進行的所有通訊,而內部的微服務使用 gRPC 和 GraphQL 。

API Gateway - Protocol transformation
API Gateway - Protocol transformation

速率限制和快取

在前面的例子中,您可以看到我們可以把通用的共享邏輯(如身份驗證)放在 API 閘道器中。除了身份驗證之外,您還可以在 API 閘道器中實現速率限制,快取以及各種可靠性功能。

超負荷的 API 閘道器

在實現您的 API 閘道器時,您應避免將非通用邏輯(如特定資料轉換)放入您的閘道器。

服務應該始終擁有他們的資料域全部所有權。構建一個超負荷的 API 閘道器,讓微服務團隊來控制,這違背了微服務的理念。

這就是為什麼你應該關注你的 API 閘道器中的資料聚合 - 你應該避免它有大量邏輯甚至可以包含特定的資料轉換或規則處理邏輯。

始終為您的 API 閘道器定義明確的責任,並且只包括其中的通用共享邏輯。

Node.js API 閘道器

當您希望在 API 閘道器中執行簡單的操作,比如將請求路由到特定服務,您可以使用像 nginx 這樣的反向代理。但在某些時候,您可能需要實現一般代理不支援的邏輯。在這種情況下,您可以在 Node.js 中實現自己的 API 閘道器。

在 Node.js 中,您可以使用 http-proxy 軟體包簡單地代理對特定服務的請求,也可以使用更多豐富功能的 express-gateway 來建立 API 閘道器。

在我們的第一個 API 閘道器示例中,我們在將程式碼委託給 user 服務之前驗證請求。

    const express = require('express')
    const httpProxy = require('express-http-proxy')
    const app = express()

    const userServiceProxy = httpProxy('https://user-service')

    // 身份認證
    app.use((req, res, next) => {
      // TODO: 身份認證邏輯
      next()
    })

    // 代理請求
    app.get('/users/:userId', (req, res, next) => {
      userServiceProxy(req, res, next)
    })複製程式碼

另一種示例可能是在您的 API 閘道器中發出新的請求,並將響應返回給客戶端:

    const express = require('express')
    const request = require('request-promise-native')
    const app = express()

    // 解決: GET /users/me
    app.get('/users/me', async (req, res) => {
      const userId = req.session.userId
      const uri = `https://user-service/users/${userId}`
      const user = await request(uri)
      res.json(user)
    })複製程式碼

Node.js API 閘道器總結

API 閘道器提供了一個共享層,以通過微服務架構來滿足客戶需求。它有助於保持您的服務小而專注。您可以將不同的通用邏輯放入您的 API 閘道器,但是您應該避免 API 閘道器的過度使用,因為很多邏輯可以從服務團隊中獲得控制。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOSReact前端後端產品設計 等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章