吳潤 武漢大學計算機學院
隨著企業級應用程序規模的不斷擴張,應用的更新、部署以及維護工作變得越來越繁重,以單體架構方式構建的應用越來越難以為繼,而微服務架構的出現為大型應用程序開辟了另一條通道,而云計算、容器虛擬化、基礎設施自動化等技術的不斷涌現,更是為微服務架構的發展提供了良好的基礎。微服務架構通過對應用進行分析,將原本單體應用中龐大冗雜的功能模塊分解成體量小,功能明確并且耦合度低的多個微服務,這些微服務相互協同完成工作。
微服務通常具備以下特點:
單一職責。在面向對象程序設計中,我們提倡高內聚、低耦合,同理,每個微服務在服務架構層面都遵循單一職責原則,每個單獨的微服務都負責特定的業務邏輯。
相互獨立。在傳統的單體架構應用中,所有的功能模塊代碼都糅合在一起,修改某個功能模塊很可能會影響到另一個功能模塊,在修改過后,還需要進行重新集成,通過測試還要進行統一打包,再部署到相應的服務器環境中。因此,在單體應用中,功能模塊的開發、測試和部署過程都會互相產生影響,而微服務架構中,每個微服務都是獨立的業務單元,有著獨立的代碼庫,并且可以單獨測試和部署。
輕量級的通信方式。微服務之間通常通過輕量級的通信機制進行通信,這些輕量級的通信方式通常是與語言和平臺完全無關的。也正因為如此,不同的微服務甚至可以使用不同的語言進行開發,增加了靈活性。
在微服務架構中,微服務都是一些功能單一、相互獨立的功能單元,其功能有限,如果需要實現某種復雜功能,則需要對已有的微服務進行適當組合,相互協作以實現各種多樣化的功能需求。因此,可以將不同功能,易于執行且簡單的微服務通過某種組合策略集成在一起實現強大的功能。
提到微服務架構,就不得不提到面向服務架構(SOA),兩者在某些方面有著不少相似之處,在SOA中,服務也是通過某種組合方式來相互協同完成某個具體功能。在web服務組合策略中,通常分為兩種方式,一種稱為編排方式(choreography),編排方式可以看做是一種消息驅動方式,實現方案大多是異步的,監聽業務事件的web服務會主動獲取消息,進行處理,然后發布自己的消息;另一種方式稱為編制方式(ochestration),編制方式的實現方案大多是同步的,這種設計方式中往往有一個流程控制服務,該服務接收請求,并按照業務邏輯調用各個web服務,最后完成任務。以上兩種服務組合方式都有對應的標準支持,分別是BPEL4WS(Business Process Execution Language for Web Services)和WS-CDL (Web Service Choreography Definition Language),BPEL4WS 適 合用于服務編制,此標準主要用于組織內部的業務流程管理,而且很多BPM產品基于此規范實現,WS-CDL是專門的web服務編排標準。
與web服務組合相類似,微服務組合采用某種適當地策略將若干個相互獨立,功能單一的微服務組合成一個功能更強大的服務,為某個具體的業務功能提供支持。不同之處在于微服務相較于web服務而言,粒度更小,功能更加獨立,而不是面向業務,因此,相比較而言,微服務組合問題面臨著更大的挑戰。
在微服務架構中,由于微服務是較小粒度的獨立功能單元,因此,通常一個具體的業務功能需要調用多個微服務,這就涉及到服務的映射和路由問題;其次,安全防護也是一個必要的考量,對來訪的用戶應該進行必要的身份認證,只有得到授權的用戶才有訪問權限;另外,可用性是保證服務穩定性的重要指標,在調用微服務的過程中,不可避免地會出現服務無響應或服務繁忙等情況,對于這些服務不可用的情況必須提供超時或熔斷處理;最后,系統也可能面臨短時間內訪問量劇增的情況,考慮到系統有限的負載能力,通過采用適當的策略減輕服務的壓力也是需要考慮的問題。
伴隨著微服務架構的出現,對于微服務組合策略的研究也隨之出現,工業界和學術界也都紛紛提出了不同的解決方案,大體上分為兩種,一種借鑒web服務組合的編排策略對微服務進行某種形式編排以實現微服務組合,另一種則是通過使用API網關來實現微服務組合。
Netflix Conductor是一個典型的借鑒web服務組合策略的微服務組合工具。Conductor支持創建復雜的業務流,這些業務流通過基于JSON DSL制定的藍圖來定義其整個執行流程,這些流程藍圖反過來也為整個業務流提供了可見性和可追溯性。另外,在業務流程的執行過程中,Conductor也支持暫停、恢復、重啟等多個控制語義,使其在運行時可以靈活應對各種突發情況。在性能上,Conductor能夠在必要時同步處理所有任務,并允許擴展數百萬個并發處理的業務流程??梢哉f,Conductor作為Netflix內部使用多年的微服務編排工具,其在多個方面都有優秀的表現。

圖1 Netflix Conductor運行時模型
文獻[5]提出了一個輕量級微服務組合平臺Medley。Medley首先為微服務組合定義一套服務組合規范,通過這些規范來約束微服務組合,然后通過編譯器將這些規范語義編譯成描述微服務組合的代碼,最后將這些代碼部署在服務器的Docker容器中執行,從而實現整個服務組合流程。
基于API網關實現微服務組合也是目前微服務領域較為常用的策略。API網關往往作為一個系統的入口,是連接所有客戶端和服務端的關鍵節點,通過一個統一的API網關,客戶端和服務端能夠非常方便地進行交互而無需了解其底層微服務細節。API網關對系統內部的細節進行了封裝,將所有非業務功能放在網關層進行處理,使其內部組織結構對API調用者透明,且對于每個調用者都提供對應的定制API。除此以外,API網關在微服務架構中還可兼具負載均衡、身份驗證、限流等多個功能職責。
相對于誕生不久的微服務架構而言,其實API網關在很多領域并不算是一個新名詞,早在微服務被提出并在業界流行起來之前,API網關就已經在金融證券領域的前置機系統上得到應用。API網關的作用在于其將客戶端和服務端有效地進行了分離,通過網關將后端的微服務進行組合并映射到對應的API,降低了客戶端和服務端之間的耦合性,在面對業務變化時也能更方便地進行功能擴展與變更,節省了開發成本,通過API網關的功能聚合作用,可以有效提高系統訪問效率。
隨著移動互聯網時代的到來,傳統的系統后臺需要支持的客戶端對象從單一的PC端逐漸轉移到手機,平板等移動端,服務場景的增多一方面對后臺的吞吐量提出了更高的要求,另一方面也無形中增大了后臺服務的復雜性,畢竟不同的客戶端由于使用場景的不同對后臺的響應需求也各不相同,而借助于API網關的強大功能,以上問題可以得到有效解決。尤其在微服務架構中,我們構建的微服務可能會面臨服務端口更改和服務實例的變更問題,不同的微服務可能采用了不同的數據協議,對于客戶端而言,其直接調用的往往是粗粒度的API,而微服務往往是細粒度的API,如果客戶端直接調用細粒度的微服務,會大大增加API調用的復雜性和系統耦合性,而這些問題也都在API網關的解決范疇之內。因此,隨著微服務架構的日益成熟完善,在很多微服務架構體系中,API網關都成為了不可或缺的一個關鍵組件。
隨著微服務架構的發展成熟,業界也相繼出現了很多成熟的API網關解決方案,常見的有Tyk、Orange、Kong、Netflix Zuul、apiaxle、Api-umbrella、Amazon API Gateway 等等。
Tyk是一個輕量級的開源API網關,基于Go語言開發[6]。在安全認證方面,Tyk支持多種認證方式,包括基本身份認證、令牌認證、HMAC簽名認證、Json Web令牌認證,也支持以上多個認證方式組合使用。在API的訪問控制方面,Tyk內置了流量限制機制,包括速率限制、請求配額和請求大小限制。Tyk提供了兩種速率限制器,即硬同步速率限制器和分布式速率限制器來實現速率限制。配額類似于速率限制,它允許在一定時間內通過一定數量的請求。Tyk支持在全局和各端點設置最大請求長度,以拒絕任何超過設定長度的請求。
Orange是一款基于OpenResty的API網關,除了具備Nginx的基本功能外,它還具備API重定向和鑒權、流量切分、訪問限速、訪問統計以及web防火墻等多種功能,是一個功能齊全的網關系統。Orange的特性之一是其內置了多個通用插件,如全局狀態統計、URL重寫、URL重定向、自定義監控、訪問限速、鑒權、WAF防火墻等。
Kong是Mashape提供的一款開源API網關,起初用于維護、管理和擴展其Marketplace中的API和微服務[8]。Kong是基于Nginx實現的,或者準確的說,Kong是一個運行在Nginx中的Lua應用程序,它比Nginx提供了更加簡單的配置方式。Kong主要包含兩個重要組件,即Kong Server和Apache Cassandra,前者用來接收API請求,后者用來存儲操作數據,可以通過增加Kong Server的數量來對Kong服務進行水平擴展,并通過負載均衡器轉發請求以應對訪問壓力。Kong的優秀之處在于其提供了大量的插件來擴展應用,為可插拔架構奠定了基礎,Orange的很多設計也正是借鑒于此。
Zuul是由Netflix開源的網關產品,其在Spring Cloud Netflix項目中的主要作用相當于路由器和服務器端負載均衡器[9]。通過Zuul的過濾器,Netflix可以實現認證、測試、動態路由、服務遷移、安全、流量管理等操作。Zuul的規則引擎支持任何以JVM語言編寫規則和過濾器,如Java和Groovy。
Apiaxle是基于Nodejs實現的開源API管理平臺,是一個免費的本地托管的API管理解決方案[10]。APiaxle系統主要包含三個組件,即Apiaxle-proxy、Apiaxle-api和Apiaxlerepl,其中,Apiaxle-proxy是系統執行代理的組件,負責身份驗證、,密鑰檢查等工作,Apiaxle-api負責負責管理用戶、密鑰等,Apiaxle-repl則提供了一個以命令行的方式來管理Apiaxle的途徑。
通過以上對API網關的簡要介紹與分析,不難看出不同的API網關之間還是存在明顯的差異。首先,API網關可能基于不同的技術基礎來實現,如Kong和Orange基于Openresty實現的,Openresty本身則基于Nginx和Lua實現,而其他大多數API網關基本是原生開發的。其次,不同的API網關可能由不同的編程語言開發,如Tyk基于Go語言開發,Apiaxle基于Nodejs開發,Api-umbrella基于Ruby開發等等。另外,不同的API網關的性能和穩定性可能也不一樣,比如Zuul有著易適用,配置簡單等優點,同時其本身還存在重定向、異常處理等亟待解決的問題,而本身基于Nginx開發的Kong和Orange等則依托于Nginx的成熟穩定,其性能和穩定性可以得到有效保障。
盡管不同的API網關之間差異明顯,但總體而言,API網關作為微服務架構中的重要一環,在連接系統客戶端與服務端并聚合微服務方面有著重要作用,為微服務調用中的安全性、準確性和穩定性提供了重要保障,為微服務組合問題提供了一個可行的解決方案。
在微服務架構系統中,API網關通常作為整個系統的唯一入口節點,其封裝了系統內部結構,對外為各個客戶端提供定制API。API網關負責服務請求路由、服務組合以及服務協議轉換,來自客戶端的所有請求首先到達API網關,然后API網關根據請求路由到對應的微服務,這些最終被調用到的微服務通常會有多個,API網關負責將它們的返回結果進行合并最終返回給客戶端。此外,一個功能完整的API網關往往還負責用戶身份認證及授權、超時處理、服務限流控制、熔斷保護、負載均衡和日志記錄等功能??梢哉f, API網關完全可以應對各種微服務組合問題。
4.3.1 服務路由
API網關授權給客戶端調用某個API,通常會預先在配置文件中配置服務路由。當客戶端訪問請求到達API網關時,根據已配置的路由規則,API網關將訪問接口映射到系統內部對應的微服務訪問接口,最終調用微服務并返回結果。當然,API網關也支持主動設置攔截或忽略某些請求, 當符合這些配置路徑的請求到達時,API網關攔截這些請求并拒絕提供服務。
4.3.2客戶端身份認證及授權
API網關作為系統的統一入口,為保障服務被安全合法地調用,身份認證自然是其必需的功能。API網關的身份認證功能通常包括用戶客戶端合法性認證、客戶端訪問授權驗證等。當用戶進入系統,系統通過其提供的有效憑證(如用戶名和密碼)為其賦予一個身份認證令牌,當客戶端請求某個服務資源時,需要首先提供前面獲得的身份認證令牌,身份認證服務通過驗證該令牌來確定該用戶請求是否合法有效。
4.3.3 服務超時處理
在理想情況下,微服務應該隨調隨用,但在實際環境中,不可避免地會出現服務器故障或者斷電等或任何導致服務實例失效的情況,在這種情況下,API網關不可能無限制地等待某個微服務響應,此時,服務超時處理就顯得尤為關鍵了。通常,在API網關中會設定一個最長允許超時時間,一旦API網關調用微服務等待時長超過了這個設定值便會立刻停止調用,防止無意義的等待。
4.3.4 服務熔斷保護處理
熔斷處理在一定程度上保證了微服務調用的容錯性,當API網關調用的某個微服務出現異常的次數到達設定閾值時,API網關會啟動熔斷保護機制,臨時切斷當前的微服務調用,以防錯誤進一步擴大,同時在合適的時機又會停止熔斷保護。常見的熔斷機制包含三種狀態,即關閉狀態、打開狀態和半開狀態,滿足相應條件的情況下三種狀態可以相互轉化。正常情況下,熔斷器處于關閉狀態,當微服務調用異常次數達到設定閾值則轉化為打開狀態,打開狀態經過了熔斷保護時間則轉為半開狀態,在半開狀態下微服務調用成功則轉為關閉狀態。

圖2 熔斷器狀態轉換機制
4.3.5 負載均衡
負載均衡在現代大型網站中早已成為標配之一,其作用是利用服務集群的優勢提高網站的性能,在API網關中也是如此。在API網關中,對API接口進行負載均衡,能充分提高其并發訪問能力,當客戶端請求到達API網關,根據設定的調度策略,該請求會被分配給合適的后臺服務器進行處理,有效的防止了服務雪崩。
4.3.6 服務限流
在微服務架構中,我們往往會面臨系統負載能力有限,而實際的請求數量卻大大超出了系統的負載上限,為了防止短時間內大量請求對系統造成過大壓力進而導致系統崩潰,對服務進行限流控制勢在必行。不同的限流策略可能不盡相同,最常用的方式是為微服務設定單位時間內的最大請求數,當這個服務的單位時間內的調用數到達設定閾值時,API網關會短暫地終止對此服務的調用。
伴隨著微服務架構的出現,微服務組合問題也稱為一個亟待解決的問題,在將粒度較小、功能單一的微服務組合為一個個具體的業務功能的過程中,所面臨的安全性、可用性以及服務映射等諸多挑戰。借鑒于Web服務組合所采用的編制和編排方法,誕生了若干針對微服務組合問題的解決方案,但終究無法面面俱到,而API網關則為微服務組合問題提供了一個較為完備的解決方法,依托于API網關的強大功能,微服務組合所面臨的問題都可以得到有效解決。隨著微服務技術的日益成熟,API網關的功能也愈發強大,相信其能夠為微服務組合問題提供更有力的支持。