為什么需要API網關?


目錄


0:00 微服務與網關(Microservices & API Gateways)

大家好,我叫Macro,今天我們談論有關微服務和網關的話題。我是Mashape的CTO,也同時是開源網關Kong的開發者之一。Kong是一個API網關,今天我們就來窺探一下它究竟是怎么工作的以及它如何運用到你的微服務架構中去。

0:23 主題(Topics)

為了明白我們為什么需要API網關,我將從單體架構vs微服務架構談起。這兩個有什么不同點呢?然后我會介紹API網關模式以及它是如何適應“面向微服務”的架構的。然后我們會討論Kong以及NGINX。

0:47 單體架構(Monolithic Architecture)

Ok,過去幾年我們目睹的一件事就是從單體應用到面向微服務的架構的過渡。我們都熟悉單體應用程序,以及它們通常的工作原理,這是一個簡單的展示。我們把所有的東西都放到一塊。而且通常也只有一個數據存儲。

通過在多個服務器上重復部署相同的巨大代碼塊,可以橫向擴展單體應用程序。所以每次我們調整應用程序時,我們其實相當於是在改動這些被放在一起的所有的模塊,因為他們是一體的。

1:45 單體應用的優缺點(Monolithic Application Pros and Cons)

每一種做法,都有利弊。單體應用程序可以比較容易地構建,而且是以更小的代碼庫來開始。我們可以在同一個代碼庫中構建和開發所有內容,這意味着我們不用擔心模塊化以及如何把不同的組件放在一起來共同工作這些事情。

而且測試起來也簡單。通常當我們測試一個單體應用時,我們一開始就只面對一個應用,然后測試我們集成的單元測試。我們只需要面對一個應用就夠了。

而且,很多IDE對單體應用已經支持的非常好了。比如Eclipse圍繞着單體應用就提供了很多成熟的測試工具,包括idea也是。

但,你也許也發現了一個代碼庫(codebase)的問題,隨着代碼量的急劇膨脹,我們把所有的都放在一個代碼庫里顯然不是一種理想的選擇。隨着時間的推移,越來越多的功能需要構建進去,代碼越來越多,在一個地方跟蹤代碼將變得更加的困難。

由於這些原因,團隊在一個大的代碼庫上迭代將會變慢。再來說個事情,比如我現在要更換數據庫存儲方案,或者想要使用一種新的技術。在單體應用中,這樣的改動通常是非常痛苦的。

由於上面所有的原因,你開始擴張你的組織。然后發生的事情就是團隊內部溝通成本變得更昂貴,因為理解代碼庫里的代碼究竟是干什么的變得更加困難。

3:55 微服務架構(Microservice-Oriented Architecture)

在過去的幾年里(一兩年吧),我們親眼目睹了我們的應用架構向微服務轉變的這個過程。容器在這個轉變中也出了很大的力氣,因為它圍繞微服務創建了一些偉大的工具,這一部分我們稍后會具體談到。

在一個微服務架構中,你把應用拆分成不同的模塊(component)。於是取而代之的是多個不同的service被彼此獨立的部署,彼此獨立的伸縮。在上面的這個例子中,客戶的訂單和發票,這些模塊將會被分別部署在他們自己的server上。

這些service之間的通信機制可以是多種格式的,通常是HTTP 或者 RPC(以及事件發布訂閱的方式)。有時候你也可為每個模塊分配不同的數據存儲schema。這樣的話,我們就把每個模塊的能力都隔離開了,而且你還讓它獨立於其他模塊而工作。

這樣也意味着很多時候你可能需要通過事件源機制來搞定一些事件觸發。在這個例子中,客戶端創建一個新的訂單。你就可以不用讓客戶端創建訂單並且生成發票,取而代之的是,你可以創建一個新的訂單,然后Orders這個模塊push一個生成發票事件,然后其他的模塊可以監聽這個事件,然后來異步生成發票。

這樣的話,你算是構建了一個異步的應用程序,它沒有依賴於客戶端並且它可以自主的為你生成發票。這也就是意味着,如果Invoices模塊down了,可以在稍后重試生成發票。

5:47 微服務架構的優缺點(Microservice-Oriented Application Pros and Cons)

面向微服務的架構也有其兩面性。微服務並不適合所有的主體,也不能hold所有的使用場景。它適合大型應用。如果您有大型應用程序,則可以將此大型應用程序拆分成不同的模塊,開發人員將能夠獨立地迭代,維護和構建這些模塊。

微服務的每個模塊(component)只做一件事情,有且僅有一件事情可以做,你可以輕松基於此迭代並且盡情的完善和創新該模塊,而且還不會影響到其他的模塊。每個模塊之間,彼此通過接口進行通信(大多數時候),比如HTTP RESTful接口。你可以改變和實驗性的搞一些實現,只要接口不改變,應用就會保持正常的運轉。

微服務,Microservices是micro。意味着如果你需要scale組織或團隊,你可以為你的團隊成員分配一些更小的,應用程序中的一些小碎片,更小的開發任務。這對於開發人員來說,有助於他們更快的理解自己要做什么,代碼是如何運作的。而且迭代起來也更快。如果他們要用到其他的模塊,他們可以使用接口去消費(consume)其他的模塊,而不需要深入到其他模塊的代碼中去。

在單體應用中,有的地方發生了錯誤,意味着整個應用程序就無法運轉了。很多時候一個bug導致整個應用程序就down了。而在微服務架構中,如果出現一個問題,這個問題是被隔離在一個特定的模塊中或者是某個service中。

這意味着整個應用程序只有那一個service處於停止狀態,而其他的模塊則可以照常運轉。就是說我們現在有Orders和Invoices兩個模塊。如果由於一些原因,開發人員在周五晚上push了一個bug到Invoices模塊上,然后導致了發票模塊不能工作。我們依然可以保存了這個發票事件。一旦Invoices模塊恢復了,我們就可以繼續生成發票了(那個之前由於bug而沒有被創建的發票又可以被創建了)。

這樣的功能我們在單體應用中也可以實現,但是由於微服務架構的推動,讓這種事件驅動的風格更加的發揚光大,而隨着時間的推移,單體應用變成了“意大利面應用”(spaghetti apps)。

面向微服務應用也有一些很典型的缺點。其中一個就是你現有有一堆不再“固定”的零部件。現在不再是單體那樣一個app在一個地方做了所有事情。現在你有多個模塊和(或)service。這些模塊要在同一時刻共同配合才能最終呈現給用戶。

這意味着你要有更強大的基礎設施能力。現在你需要有一種魔法,要能簡單地部署、伸縮、以及監控和管理這些不同的模塊,這些獨立的模塊。這也是這些年來實時的在線監控和分析技術變得如此火爆的原因之一吧。因為一旦你是面向微服務的架構,你就必須去監控每一個碎片(零部件)並且要在一個集中的地方可以看到你的模塊們的運行狀態。

在單體中,你只有一個代碼庫來保存,執行並且所有的entity都在一塊。在微服務架構中,我們有很多不同的模塊,他們都彼此獨立運行,並且只干一件事情。

這就意味着你現在有一個可用性的問題:service們也許會go down 不可用。或者還會有一致性問題:也許你需要把這些微服務scale到多個數據中心。所以你在創建一個應用時,就要把這些問題都要考慮進去。

如果你想要測試一個service,有的簡單,有的比較難。這取決於你要測試的內容。

如果只是測試一個獨立的模塊,那就比較簡單。但要測試一個多重依賴的那種的話可能就比較復雜了。通常的話,如果你想要測試一個構建於微服務架構之上的應用的話,前提條件就是你必須要同時啟動所有的這些模塊,這樣可以確保彼此都可以相互通信,並且要成功地實現了集成測試。

11:18 為什么需要API網關?

Ok,為什么我們需要一個API網關呢?

我們總是聽到編排這個詞,所以我喜歡這張幻燈片 – 它展示了一個樂隊,然后有個指揮家,下面一堆人(微型服務)演奏自己的樂器。這個指揮家(API網關)可以以某種方式來協調我們的架構如何處理請求。

11:54 API網關模式(API Gateway Pattern)

API 網關模式意味着你要把API 網關放到你的微服務們的最前端,並且要讓API 網關變成由應用所發起的每個請求的入口。這樣就可以明顯的簡化客戶端實現和微服務應用程序之間的溝通方式。

以前的話,客戶端不得不去請求Customers,然后再到Orders,然后是Invoices。客戶端需要去知道怎么去一起來消費這三個不同的service。使用API網關,我們可以抽象所有這些復雜性,並創建客戶端們可以使用的優化后的端點,並向那些模塊們發出請求。

12:53 優化后的端點(Optimized Endpoints)

例如,優化的端點。如果我們假設客戶(Customers),訂單(Orders)和發票(Invoices)每個模塊都返回不同的JSON響應,並且假設客戶端想要檢索此信息。有兩種方法。一種方式是,客戶端向客戶(Customers)模塊發出GET請求以檢索客戶,然后到訂單(Orders),然后到指定訂單的發票(Invoices)。

第二種方式是我們可以通過使用API網關來抽象此客戶端實現的復雜性。然后,API網關可以公開一個特定的端點,在這個端點上將產生請求,然后在[網關]消費了微服務之后返回給客戶端一個唯一的響應(response)。

也就是說,比如,我們可以把很多的response折疊成一個,request也是一個。這樣對我們幫助很大,而且特別是對於手機等其他移動客戶端來說特別的受益。這樣就可以加速我們的客戶端的實現。而且可以輕松的做一些替換。

有一個很nice的事情,就是API網關讓我們的客戶端不用再需要知道和關心模塊的地址(address)了。網關負責來搞這些事情,你只需要知道網關就好了。你可以去改變實現而且還可以改變API接口。不過通常來說,你改變接口后,會增加客戶端出問題的風險。

使用API網關后,你可以在單獨的層上有效地抽象,這樣你就可以更改實現和接口,同時保持現有客戶端的公共接口相同。這意味着你總是可以做一些調整的事情。

API網關對於那些從單體轉變到微服務的應用來說也是一個非常有幫助的工具。如果你現在維護一個單體應用,你就可以把一個API網關放到這個單體的最前面,然后你就慢慢地開始把單體拆分成很多的不同的微服務,在這個過程中,客戶端就一直是通過API網關來保持自己的運作,這樣讓你的遷移過程更優雅!

API網關將隨着時間的推移實現和消費后端的上游service,同時保持客戶端的正常工作。擁有一個API網關可以幫助我們實現這樣的過渡。

15:28 中心化中間件(Centralized Middleware Functionality)

當然了,創建一個優化的端點僅僅是API網關的好處之一。你還可以通過API網關中心化中間件的能力。當你開始創建越來越多的服務時,你會發現自己面臨了一個新的問題 – 就是你發現你需要對一些服務進行身份驗證和流量控制。

有的服務是public的;有的是private的;有的則是合作伙伴的API,這些你只能提供給一些特定的用戶。遲早你會發現自己在實現每個微服務時總是一次次的重復編寫一些相同的代碼,這些代碼其實都是可以抽象為中間件的。

這顯然不是每個微服務應該去關注的事情。API網關才應該把這件事情攬下,也就是說微服務只負責接收進來的request-然后返回一個類似JSON格式的response即可。然后API網關就把這些例如身份驗證、日志(logging)以及流量控制都歸於麾下。

在這個slide,還要介紹的就是最下面的Faas(function as a service),這個是一個很酷的東西。它意味着你正在消費的某個API端點可能正在地球的某一個角落在做一些事情。

它也許運行在一個serverless的架構之上,或者並沒有運行在你自己的server上。這意味着你同樣可以在這些能力前面前置一個API網關,也可以在他們之上運行一些上面所說的那些中間件。

17:24 Ops: Blue/Green Deployments

這里我只是向你們展示了一些使用場景,然后讓你知道它是如何讓我們的“生活”變得更簡單。比如,布署,deploy這件事情。在微服務架構中,一個特定的service也許在一天內要被deploy很多次(它不像單體時布署是一件艱難的事情)。

在單體應用中,布署(deployment)往往是一件比較耗時和緩慢的事情,因為你每次做的一點點改變,你都不得不要把一整個單體應用重新布署一遍。而且隨着應用規模的增長,布署這件事情就變得越來越復雜。而在微服務中呢?你可以獨立的去布署一個模塊很多次,因為模塊布署起來要更快更容易,因為只需要布署一個小小的塊。

而且如果你需要,你還可以實現blue/green布署,API網關可以讓這件事情通過一種簡單的方式實現變為可能。比如,如果有一些Customer模塊是1.0.0版本,有些Customer模塊則是1.0.1版本。網關能夠知道這些所有的版本的模塊的location,然后提供接口可以讓你從舊的版本切換到新的版本。

18:50 Ops:金絲雀發布(Canary Releases)

另一種發布策略是金絲雀發布(canaryreleases)。當我們創建軟件的時候,有時候你不希望讓所有的流量都一次性的到達新的版本,因為那個新的版本也許並沒有測試地很充分。

金絲雀發布策略允許你直接只導入指定量的流量到新的版本,API網關就可以幫你來做這件事情。你可以配置10%的請求到新的版本,然后一旦你確保了新版本沒有bug,你可以把流量切換到100%。

19:34 Ops:負載均衡( Load Balancing)

API網關的另外的一個能力就是可以負載均衡。在一定場景下,API網關可以是負載均衡器。API網關知道所有的service的地址和位置,所以你可以在API網關和上游service之間加一個負載均衡器。或者它本身就是一個負載均衡器。

當它是負載均衡器時,API網關就可以利用諸如Consul或etcd這些服務發現工具來負載均衡請求(request)。

每次你去請求一個DNS地址,服務發現(service‑discovery)工具就會給你一個新的IP地址。一般會在DNS這一層中做一些類似round-robin等策略的負載均衡。

20:36 Ops: 斷路器(Circuit Breakers)

現在我們閉目想想,假定你的某個service突然停止了工作,然后返回了大量的錯誤。

API網關可以幫你實現斷路器(circuit breakers)的能力,也就是說超過了指定的閾值,API網關就會停止發送數據到那些失敗的模塊。

這樣就給了我們時間來分析日志,實現修復以及push更新。通常當你發現一個模塊下的某個實例失敗后,這時候這個模塊依然還會接收流量,然后這個有問題的模塊還調用了其他的模塊,這樣就會發生級聯故障,或者叫雪崩。

斷路器通過簡單的斷開流量的方式,這樣就不會有新的請求到達那些有問題的實例,這時候我們就有相對充分的時間來修復和解決問題。

21:35 構建微服務vs運行微服務(Building vs Running a Microservice)

在這里我想說明一個經常被誤解的內容。有時,產品經理和軟件工程師認為,構建API與運行API相同,因此構建微服務與運行微服務相同,但這是兩個不同的問題。他們必須以不同的方式解決。

22:01工作量分布(Division of Labor)

我認為構建API通常是構建微服務器所需的工作量的50%。這是一個大概的估計,並不是把每個人都考慮到了。現在我們有一個API運行,它可以接受請求和返回響應,但是我們如何處理管理,身份驗證,流量控制和速率限制?

那么我們用戶的速率限制之后的下一步就是將這些用戶的一小部分列入白名單的問題,允許這一部分人無論如何都不會被限制。這算是一種更高端的速率限制。

微服務可以為你提供更多,不僅僅是一個你可以消費的API。

然后是監控分析 - 這是非常重要的。你需要持續地監視和跟蹤模塊和文檔的狀態。 如果你有API,你還需要有適當的文檔。這不僅對公共開發人員而言是重要的,而且對於組織內部的開發人員也是重要的。

比如你有一個語音API以及一個SMS API,如果您希望紐約和舊金山的兩個團隊合作,團隊只需要發布一個API接口的文檔,然后你組織內的任何人都可以使用那個API。保持文檔最新是非常重要的。

這也是通常在創建新API時一般不會納入那50%的一部分內容,但這確實是面向微服務的體系架構的一部分。

 

 

 

 

本文作者:賀卓凡譯 Macro著
原文鏈接:https://mp.weixin.qq.com/s/XTzRr0eR6ybpNFGJ57cVkA
版權歸作者所有,轉載請注明出處


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM