架構設計基礎-軟件架構設計學習第二天(非原創)

文章大綱

一、架構需求分析
二、架構願景分析
三、架構設計原則
四、必備設計-API網關
五、參考文章

 

一、架構需求分析

1. 需求收集與分析

需求分析的前期工作是願景描述及願景分析, 即願景分析就是需求的前期調研.
從軟件過程來看,需求分析是一個承上啓下的階段–“上承”願景,“下接”設計。需求分析的工作內容包含如下三方面:
1.1 需求捕獲: 理解溝通
需求捕獲: 從各個方面收集需求, 並理解需求.典型的需求捕獲是使用“需求採集卡”:需求描述、需求提出者、需求記錄者、需求類型等。

1.2 需求分析:做什麼,有哪些問題
需求分析:需求捕獲得到的是“原始需求”,而需求分析則對各方面收集到的需求進行分析、整理、歸納、論證形成明確的需求。比如, 產品經理說,現在系統不穩定, 需要重構架構保證系統穩定. 這只是一個願景, 我們需要把這個需求形成一個明確的需求: 可行性99.99%, 要完成這個指標,需要做哪些工作.

1.3 系統分析:原因是什麼, 怎麼做
三者不是獨立無關的階段,而是相互伴隨、交叉進行的。

2. 需求分類

需求可分類爲三類:
(1)功能需求:更多體現各級直接目標要求,系統具體要做什麼. 有哪些功能點.
(2)質量需求:運行期質量 + 設計質量+用戶質量+系統質量.
(3)約束需求:業務環境因素 + 使用環境因素 + 構建環境因素 + 技術環境因素.

ADMEMS矩陣,可作爲需求梳理和需求評審的工具:

 

3. 需求優先排序

架構設計的本質目的是爲了解決業務,架構設計也並不是面面俱到,而是識別問題有針對性的解決, 所以要先了解系統最需要解決的是什麼。

例如系統的複雜度來源於業務邏輯複雜,功能耦合度嚴重,架構師設計TPS達到50000/s的高性能架構沒有意義。

出現問題主要爲了滿足“高可用”“高性能”“可擴展”三個方面,就算老闆拍腦袋要求同時滿足三高,也要分優先級。

比如線上運行的系統可能存在的問題:

運行效率低下,升級複雜,容易出錯。

開發效率低下。

小問題不斷,不好定位。

解決方法:

列出主要的複雜度問題

根據業務、技術、團隊等情況進行排序

優先解決最主要的複雜度問題.

4. 需求分析總參考圖

 

二、架構願景分析

1. 架構設計流程

 

2. 願景和目標區別

有時候我們經常把願景和目標混爲一談,我們首先需要區別願景和目標:
(1)願景籠統,目標具體,。比如:架構設計做做到高可用,高性能,高可擴展,這些是籠統的概念,沒有具體的指標要求。
(2)目標是即將實現,能夠通過努力實現的規劃,願景是一幅前景,能夠指引我們前進的理想。
(3) 願景有助於確定發展目標,發展目標爲實現願景服務。
(4)架構願景:是一種團隊內心的願望,是腦筋的一幅圖畫,是一種驅動力,願意實踐、追求,來達到某一個境界,能追求到某一種成就。是團隊成員希望架構往哪個方向發展,包括具體目標、設計原則、質量要求。
(5)架構目標:架構達成某些具體的指標,比如可用性達到99.99%等。
(6)因此我這裏認爲架構的願景分析是包含目標.

3. 架構願景的層次

架構的願景是相對於一個範圍來說的,在一個特定的軟件功能範圍之內,談架構願景纔有實際的意義,例如針對軟件的全局或某個子系統/模塊。在這個特定的範圍中,訂立了架構願景之後,這個範圍內的所有設計原則將不能違背架構願景。這是非常重要的,是架構願景的最大的用處。有了這樣的保證,我們就可以保證設計的一致性和有效性。任何一項設計的加入,都能夠融入到原先的架構中,使得軟件更加的完善,而不是更加的危險。

我們根據架構適用範圍的不同,把架構願景分爲幾個類別討論:

 

3.1 軟件系統全局(架構模式)
軟件全局的架構是我們所最關心的,因此也會花費最多的筆墨。
軟件全局中的架構願景一般很難具體化到代碼級別,其實你會發現,就算是具體化到了代碼級別,也會因爲實際中存在的問題,導致代碼沒有太多的價值。因此,爲軟件全局設置的架構願景可以以原則、或是架構模式的方式體現,並用自然語言或僞代碼描述。例如,可以爲一個系統規定三層架構作爲其願景,並指出三層的分類原則和具體目標。注意,我們需要指出分類原則,否則規定三層架構並沒有太大的意義,因爲三層架構隨着實現平臺的不同、開發人員的不同而有很大的差異,如果不能夠規定一個可操作的規範,那麼願景是沒有意義的。

3.2 子系統/模塊級、或是子問題級的架構願景
這時候的架構願景已經是比較明確的了,因爲已經存在明確的問題域。例如界面的設計、領域模型的設計、持久層的設計等。這裏的願景制定本質上和全局的願景制定差不多,具體的例子我們也不再舉了。但是要注意一點,你不能夠和全局願景所違背。在操作上,全局願景是設計團隊共同制定出來的,而子/系統模塊級的架構願景就可以分給設計子團隊來負責,而其審覈則還是要設計團隊的共同參與。這有兩個好處,一是確保各個子模塊(子問題)間不至於相互衝突或出現空白地帶,二是每個子設計團隊可以從別人那裏吸取設計經驗。

在設計時,同樣我們可以參考其它的資料,例如相關的模式、或規範(界面設計指南)。在一個有開發經驗的團隊,一般都會有開發技術的積累,這些也是可供參考的重要資料。

我們在這個層次的願景中主要談一談子模塊(子問題)間的耦合問題。一般來說,各個子模塊間的耦合程度相對較小,例如一個MIS系統中,採購和銷售模塊的耦合度就比較小,而子問題間的耦合程度就比較大,例如權限設計、財務,這些功能將會被每個模塊使用。那麼,我們就需要爲子模塊(子問題)制定出合同接口(Contact Interface)。合同的意思就是說這個接口是正式的,不能夠隨意的修改,因爲這個結構將會被其它的設計團隊使用,如果修改,將會對其它的團隊產生無法預計的影響。合同接口的制定、修改都需要設計團隊的通過。此外,系統中的一些全局性的子問題最好是提到全局願景中考慮,例如在源自需求模式中提到的信貸帳務的例子中,我們就把一個利息計算方式的子問題提到了全局願景中。

3.3 代碼級的願景 (代碼設計模式)
嚴格的說這一層次的願景已經不是真正的願景,而是具體設計了。但是我們爲了保證對架構設計理解的完整性,還是簡單的討論一下。這一個層次的願景一般可以使用類圖、接口來表示。但在類圖中,你不需要標記出具體的屬性、操作,你只需要規定出類的職責以及類之間的相互關係就可以了。該層次願景的審覈需要設計子團隊的通過。

而設計細分到這個粒度上,執行願景設計的開發人員可能就只有一兩個左右。但是比較重要的工作在於問題如何分解和如何歸併。分解主要是從兩個維度來考慮,一個是問題大小維,一個是時間長短維。也就是說,你(設計子團隊負責人)需要把問題按大小和解決時間的長短分解爲更細的子問題,交給不同的開發人員。然後再把開發人員提出的解決方法組合起來。

4. 架構目標

4.1 提出期望目標
期望目標也是來源於需求,主要指客戶(可能是老闆)或其他利益相關人提出的項目(產品)願景。願景表達了客戶的目標以及對系統的期望。從願景中我們可以獲得許多架構分析所需要知道的知識,例如明確客戶最期望達到的目標,以此可以確定場景與風險的優先級;瞭解客戶的不同目標,可以由此識別系統客戶的不同角色,明確不同的利益相關人的態度。
(1)業務響應能力:
降低系統耦合, 提升對變化的響應速度。
改善系統架構, 更好地支持業務擴展。
建立流程引擎, 更靈活地支持業務流程變化。

(2)系統質量:
合理地增加或減少系統間交互及補償, 提升系統性能、 穩定性。

(3)開發效率:
合理劃分系統, 通過系統職責的分離, 對開發組的職責進行合理分配, 同時建立更完整的公共平臺、 基礎框架、 基礎類庫, 提高開發效率。

(4)運維水平:
完善配置、 監控、 預警、 日誌系統, 提升系統運維配置效率及排查問題的速度.

4.2 架構具體目標:衡量系統好壞的標準
具體目標指標如下:
(1)正確性:系統首先需要正確,運行穩定
(2)可用性: 系統必須非常可靠,一般業界更傾向用 N 個9 來量化可用性, 最常說的就是類似 “4個9(也就是99.99%)” 的可用性。
(3)開發效率: 降低開發成本和降低公司在快速鉅變的行業裏面的時間和機會成本。互聯網目前是一個快魚吃慢魚的時代,已經不是大魚吃小魚了。因爲小魚在一夜之間就長大了,把大魚吃掉了。
(4)伸縮性: 用戶激增的時候,系統可以伸縮來支持用戶的增長或流量高峯。
(5)安全性:安全也是一個商業公司的命脈,攻擊、泄密、破解,前一段鬧的沸沸揚揚的各種用戶信息泄露,足以說明安全的重要性。
(6)擴展性:在增加新模塊或者新的技術時,能比較容易的擴展。
(7)高性能:性能其實也是用戶體驗的一部分,尤其是用戶量不斷增多,性能是節省成本的重要手段。
(8)可維

 

4.3 確定架構質量要求

 

三、架構設計原則

如何設計出一個好的架構,不像數據公式或者定律,很難一概而就。很多時候是設計者(架構師)的各種設想,各種權衡折中而符合系統需求的智慧輸出。但我們掌握前人總結的經驗,讓我們站在巨人的肩膀上高山遠矚。一些好的架構設計原則可以確保設計決策在一定程度上能夠滿足需求。

1. 形成架構原則的過程

形成架構原則的過程:

 

架構原則要SMART

 

2. 常見的架構設計原則

2.1 N+1設計
開發的系統在發生故障時,至少有一個冗餘的實例
廣泛地應用在從數據中心設計到應用服務的部署:
在發生故障時,系統至少要有一個冗餘的實例。
必須確保一個爲自己,一個爲客戶、 一個爲失敗

2.2 回滾設計
確保系統可以向後兼容
如果很久才能修復服務,那麼就要在一定的時間範圍內完成回滾。
災難性的事故,例如損壞客戶數據,往往在部署後好幾天纔出現。
系統最好按照預先的設計,通過發佈或回滾解決問題。

2.3 禁用設計
可以關閉任何發佈功能
當設計系統,特別是與其他系統或服務通訊的高風險系統時,要確保這些系統能夠通過開關來禁用。這將爲修復服務提供額外的時間,同時確保系統不因爲錯誤引起詭異需求而宕機。

2.4 監控設計
在設計階段就要考慮監控,而不是在部署完成後,通過監控發現系統的可用性問題。
(1)通過監控使系統自我診斷、自我修復成爲可能。
(2)通過監控確定系統可預留空間的使用情況。
(3)通過監控掌握系統之間的交互關係,發現瓶頸
如果監控做的好,不僅能發現服務的死活,檢查日誌文件,還能收集系統相關的數據,評估終端用戶的響應時間。如果系統和應用在設計和構建時就考慮好監控,那麼即使不能自我修復,也至少可以自我診斷。

2.5 多活數據中心設計
數據是否全部集中在一個數據中心?
讀寫是否分離?
是否所有的客戶信息都共享同一個數據結構?
服務調用是否允許延時的存在

2.6 採用成熟的技術
(1)工程師傾向於學習和實施性感時髦的新技術。因爲新技術可以降低成本、減少產品上市時間、提高性能。不幸的是,新技術也往往有較高的故障率。如果把新技術應用在架構的關鍵部分,可能會對可用性產生顯著的影響。
(2)最好爭取在多數人採用該技術的時候進入,先把新技術用在對可用性要求不高的功能上,一旦證明它可以可靠地處理日常的交易,再將此技術移植到關鍵任務領域中去。

2.7 故障隔離
避免單一業務佔用全部資源。避免業務之間的相互影響 2. 機房隔離避免單點故障。
不共享原則:理想情況是負載均衡、網絡前端、應用服務器、數據庫,絕不共享任何服務、硬件和軟件。
不跨區原則: 不同隔離區之間無通訊,所有服務調用必須發生在同一個故障隔離區。

2.8 水平擴展
什麼是水平可擴展?平臺的水平擴展是指隨着業務的發展,當需要擴大平臺的服務能力時,不必重構軟件系統,通過增加新的設備來滿足業務增長的需要。

 

X軸擴展:服務器拆分。平臺的服務能力可以在不改變服務的情況下,通過添加硬件設備來完成擴容。
Y軸擴展:數據庫拆分。平臺的服務能力通過不斷地分解和部署服務來完成擴容。
Z軸擴展:功能拆分。平臺的服務能力可以按照客戶不斷分解和部署來機器 完成容量的擴展。(比如按用戶uid來分表分庫等)

 

2.9 非核心則購買
工程師往往有自己研發所有系統的衝動。
系統研發要投入資源,系統維護更要長期投入。
影響核心產品到市場的速度。
如果可以形成差異化的競爭優勢,那麼自己做,否則外購。

2.10 使用商品化硬件
在大多數情況下,便宜的是最好的。
標準、低成本、可互換、易於商品化是商品化硬件的特徵。如果架構設計得好,就可以通過購買最便宜的服務器輕鬆地實現水平擴展,前提是所有商品化硬件的總成本要低過高端硬件的總成本。

2.11 快速迭代
小構建:小構建的成本較低,可以確保投資可以產生價值。
小發布:發佈的失敗率與變更數量相關,小發布失敗率較低。
快試錯:可依市場反饋,快速迭代,加快TTM,優化用戶體驗

2.12 異步設計
同步系統中個別子系統出現故障會對整個系統帶來影響。
同步系統中性能最慢的子系統成爲整個系統性能的瓶頸。
同步系統中擴展性最差的子系統是整個系統擴展的瓶頸。

2.13 無狀態設計
無狀態的系統更利於擴展,更利於做負載均衡。
狀態是系統的吞吐量、易用性、可用性、性能和可擴展性的大敵,要盡最大可能避免。

2.14 前瞻性設計
Now :目前正使用系統的架構、設計、能力、性能和擴展性。
Now+1: 下一代預研系統的架構、設計、能力、性能和擴展性。
Now+2: 下一代規劃系統的架構、設計、能力、性能和擴展性

2.15 自動化
設計和構建自動化的過程。如果機器可以做,就不要依賴於人. 人常犯錯誤,更令人沮喪的是,他們往往會以不同的方式多次犯同樣的錯誤。

3. 架構設計的關鍵原則

3.1 一個好的設計擁有以下幾點
(1)解決現有需求和問題
(2)把控現實的進度和風險
(3)預測和規劃未來,不要過度的設計,從迭代中演進和完善。
在開始設計之前,思考一下關鍵的原則,將會幫助你創建一個最小花費、高可用性和擴展性的架構。

3.2 分離關注點
將應用劃分爲在功能上儘可能不重複的功能點。主要的參考因素就是最小化交互,高內聚、低耦合。但是,錯誤的分離功能邊界,可能會導致功能之間的高耦合性和複雜性

3.3 職責單一
每一個組件或者是模塊應該只有一個職責或者是功能,功能要內聚。

3.4 最小知識原則
一個組件或者是對象不應該知道其他組件或者對象的內部實現細節。

3.5 不重複原則
你只需要在一個地方描述目的。例如,特殊的功能只能在一個組件中實現,在其他的組件中不應該有副本。

3.6 最小化預先設計
只設計必須的內容。在一些情況,你可能需要預先設計一些內容。另外一些情況,尤其對於敏捷開發,你可以避免設計過度。如果你的應用需求是不清晰的,最好不要做大量的預先設計。

3.7 低耦合、高內聚
防止變異(使用接口和適配器防止變異)、關注分離。

3.8 關注分離
橫向分層、縱向分區
(1) 將有關事務模塊化,封裝到單獨的構件(例如子系統)中,並且調用其服務;
(2) 使用裝飾者,將所關注的事物(例如安全)置入Decrator對象中,Decorator對象包裹內部類並提取其服務,裝飾者在EJB技術中被稱爲容器,EJB容器圍繞內部對象的業務邏輯,在外部的裝飾者中增添安全檢查;
(3) 使用後便以和麪向方面的技術(Aspect-oriented),比如AspectJ以對開發者透明的方式支持在編譯之後將橫切面關注織入代碼。

3.9 關注點分離之道
好的架構設計必須把變化點錯路有致地封裝到軟件系統的不同部分,爲此,必須進行關注點分離。關注點相互分離,也就是說系統中的一部分發生變化,不會影響其他部分。即使需要改變,也能夠清晰地識別出哪些部分需要改變。如果需要擴展架構,影響將會最小化,已經可以工作的每個部分都可以繼續工作。

首先,可以通過職責劃分來分離關注點。面向對象設計的關鍵所在,就是職責的識別和分配。每個功能的完成,都是通過一系列職責組成的協作鏈條完成的,當不同職責被合理分離之後,爲了實現新的功能只需構建新的協作鏈條,而需求變更頁往往只會影響到少數職責的定義和實現。

其次,可以利用軟件系統各部分的通用性的不同進行關注點分離。不同的通用程度意味着變化的可能性不同,將通用性不同的部分分離有利於通用部分的重用,頁便於對專用部分進行修改。

另外,還可以先考慮大粒度的子系統,而暫時忽略子系統是如何通過更小粒度的模塊和類組成的。在實際中,軟件架構師常常將系統劃分爲一組子系統,併爲子系統定義明確的藉口,其中的細節將隨其後的開發工作慢慢展開。

根據職責分離關注點、根據通用性分離關注點、根據不同粒度級別分離關注點是三種不同維度的思維方式。

3.10 非侵入性原則
那麼什麼是架構的侵入性呢?所謂侵入性就是指的這個架構設計出來的部件對系統的影響範圍,比如框架的侵入性就很高,因爲在一個工程中引入一個框架,你的整個設計都必須圍繞這個框架來進行,一旦使用了,框架的可替代性幾乎爲0,這樣子就是搞侵入性。組件的侵入性就比較低,比如ibaties,他可以在任何java框架下使用,甚至可以和其他ORM組件共存,你僅僅需要引入,配置,然後就可以使用了,你也可以用其他的ORM替換他,所以......這個體驗應該是很愉快的。
所以話說回來說到如果我們在設計一個通用架構的時候就應該注意到這個一個非常重要的地方,除非我們只是自己拿來用用,否則我們不應該假設我們的設計的用戶已經具備怎麼怎麼樣的環境或者是需要做什麼特殊的設計才能夠使用。
這裏打個比方,假如說我們在設計一個通用權限管理什麼什麼的時候我們就要想好,這是一個組件,還是框架,還是一個現成系統(複用通過改改代碼實現,其實個人覺得這種設計很低級,雖然有的這樣子的東西功能確實豐富)。確定了目標之後我們纔好開始下一步,比如確定是一個框架的話可能發揮要自由一些,因爲不需要高度的內聚,不過可能因爲框架要設計的方方面面太多了,所以老是覺得個人的力量不足以搞這種東西出來。如果是組件的話就需要高度的內聚來實現非侵入式,比如引入DLL的時候還需要讓所有頁面繼承自某個基類頁就不算是一個good idear。

四、必備設計-API網關

1. 網關概念介紹

API Gateway(API GW / API 網關),顧名思義,是企業 IT 在系統邊界上提供給外部訪問內部接口服務的統一入口。在微服務概念的流行之前,API網關的實體就已經誕生了,例如銀行、證券等領域常見的前置機系統,它也是解決訪問認證、報文轉換、訪問統計等問題的。

百度百科:API網關是一個服務器,是系統的唯一入口。從面向對象設計的角度看,它與外觀模式類似。API網關封裝了系統內部架構,爲每個客戶端提供一個定製的API。它可能還具有其它職責,如身份驗證、監控、負載均衡、緩存、請求分片與管理、靜態響應處理。

API網關方式的核心要點是,所有的客戶端和消費端都通過統一的網關接入微服務,在網關層處理所有的非業務功能。通常,網關也是提供REST/HTTP的訪問API。服務端通過API-GW註冊和管理服務。

2. API網關分析設計

2.1 宏觀分析要素
安全性問題
企業在把服務暴露給外部使用時,首先要確保服務使用的安全,防止外部的惡意訪問對公司業務的影響,特別是涉及交易方面的服務,更是要全面考慮安全性。爲確保安全,需要考慮在通訊鏈路的建立、通訊數據的加密、數據的完整性、不可抵賴性等方面。

性能問題
作爲企業API的入口,所有的請求都會經過API網關進行轉發,可想而知,對API網關的訪問壓力是巨大的,有的網站甚至達到每分鐘上千萬的訪問量。特別是在一些互聯網企業,海量的移動終端每時每刻都需要與後端的服務進行交互,如果不能保證網關的高性能,企業在網關層需要投入大量的設備和成本。曾在一家互聯網公司發生過,由於網關性能問題,網關的機器數量,需要與後臺服務器的數量保持同步增長。這種情況顯然是企業服務忍受的。

高可用問題
API網關作爲邏輯上的單點,一旦發生問題,將造成企業服務的不可用,對企業來說可能造成的致命的影響。計算短時間的不可用,也會給企業帶來直接的經濟損失。所以,如何保證API網關的7*24小時的穩定運行,網關的自動伸縮、API的熱更新等問題,都是企業級的網關需要考慮的。

擴展性問題
前面說到,企業網關提供了一個腳手架,一些非功能性的問題,例如日誌、安全、負載均衡策略、鑑權等。這些插件會隨着企業業務規模等的變化進行不斷的強化與調整。這就需要網關層提供這樣一種機制,使得可以靈活地進行這些調整和變化,而不用頻繁對網關層進行改動,確保網關層的穩定性。

API高效運維的問題
API在上線、發佈過程中,都需要涉及到網關層的配合,例如,需要網關層知道API發佈的地址,API的接口形式、報文格式,也需要網關層對後臺API進行封裝。在API調整後,需要作出相應的修改。所以,API網關設計時,需要明確網關層與服務層的職責切分與協作模式,使得API的管理、發佈更加高效。

API全生命週期的管理
API服務的全生命週期,包括服務的開發、測試、上線發佈;服務使用的申請、開通;服務分類分級別的管理、服務使用情況的監控、計費等等。
一個企業可能會暴露成百上千個API,日常也會經常進行API的發佈、升級、改造、下架等操作。對不同的服務,不同的訪問者,需要提供不同的服務訪問策略。有的商業API公司,還需要對API的使用進行付費。所以,與API網關配套的,需要一套完善的自助系統,提供給服務的提供者、管理者、使用者,來對服務的發佈、使用、和運營。

2.2 具體情況分析
功能需求
1、API 生命週期管理功能:
覆蓋 API 的定義、測試、發佈的整個生命週期管理,便捷的日常管理、版本管理,支持熱升級和快速回滾

2、開發和使用支持功能:
提供頁面調試工具,自動生成 API 文檔和 SDK,大大降低人力成本。

3、安全防護功能:
API 請求到達網關需要經過嚴格的身份認證、權限認證,才能到達後端服務。支持算法簽名,支持 SSL 加密。

4、流量控制功能:
可控制單位時間內 API 允許被調用次數。用來保護企業的後端服務,實現業務分級和用戶分級。 支持對 API 流控,您可以根據 API 的重要程度來配置不同流控,從而保障重要業務的穩定運行; 支持用戶、應用和例外流控,您可以根據用戶的重要性來配置不同流控,從而可以保證大用戶的權益; 流控粒度:分鐘、小時、天。

5、請求管理功能:
可根據配置進行參數類型、參數值(範圍、枚舉、正則、Json Schema)的校驗,減少後端對非法請求、無效請求的資源消耗和處理成本。可以在 API 網關定義參數映射規則,網關通過映射規則將後端服務通過映射翻譯成任何形式,以滿足不同用戶的不同需求,從而避免功能重複開發。

6、監控告警功能:
提供實時、可視化的 API 監控,包括:調用量、調用方式、響應時間、錯誤率,讓您能夠清楚的瞭解 API 的運行狀況和用戶的行爲習慣。
支持自定義報警規則,來針對異常情況進行報警,降低故障處理時間。
提供可訂閱的數據分析報表和智能分析。

高性能設計
傳統的基於線程的併發模型(Thread-based concurrency),爲每一個請求分配一個線程或進程。這種模型編程簡單,可以將處理一個完整請求的代碼編寫在一個代碼路徑中。這種模型的弊端是,隨着線程(進程)數的上升,操作系統在這些線程(進程)之間的頻繁切換,將急劇降低系統的性能。

 

高可用設計
1、無狀態設計原則。
網關層爲保證高可以,易於伸縮,快速啓動,需要設計成無狀態的。用戶的狀態數據我們通常使用session對象來封裝,網關層要設計成無狀態的,也就是說,不能由網關來負責session的維護。那由誰來維護session相關的信息呢?我們是採用cookie+session服務器的方式;
a) 用戶在登錄頁完成登錄操作後,服務器會生成一個登錄session信息,保存起來,設置個失效時間,並設置到用戶的cookie裏
b) 用戶後續的每次請求裏會帶着這個cookie信息,服務端會對這個cookie信息進行校驗,通過了就認爲是合法用戶,執行請求操作

2、優雅下線原則
當需要撤掉一臺網關服務的時候,不是直接結束網關進程,而是先關閉監聽套接字,但是繼續爲當前連接的客戶提供服務,所有客戶端的服務完成後,在把進程關閉。

3、Slow start特性
當網關監聽到有一臺新的服務註冊上來時,考慮到有些服務啓動後,剛開始會有許多初始化的工作,此時服務對請求的響應速度是比較慢的。如果一開始就給這臺服務分配太多的壓力,有可能導致服務瞬間被壓垮。爲了避免這種情況,網關層需要考慮支持Slow Start特性。即,經過一段時間,逐漸把壓力增加到預設的值。

4、擴展性設計
我們知道,網關對請求的處理,可以分爲三個階段:接受請求、路由並轉發請求、接受服務的返回數據並返回給請求者,除此之外,還有一種情況是處理錯誤。所以我們也可以在這四個地方添加擴展點。
(1)接受到請求後
(2)定位到一個服務,並準備轉發之前
(3)接受到服務的返回數據,返回給客戶端之前
(4)當服務調用失敗後
攔截器的處理順序,可以分爲兩大類:一類爲網關平臺自帶的攔截器,例如安全校驗、日誌記錄等;一類爲網關層邏輯開發的,例如格式轉換等。一般來說,網關先執行網關平臺自帶的攔截器,再執行爲了業務邏輯編寫的攔截器。當然,網關也需要提供一種機制,可以較容易地調整攔截器的執行順序。最簡單的一種方法,就是給每個攔截器定義一個優先級,網關按優先級順序依次調用各攔截器。
對網關層來說,它接收和處理的數據都是Request對象,網關層在接收到請求後,把請求封裝爲Request對象,爲了讓後續的filter能夠獲得這個對象,可以考慮把Request對象保存在線程變量中。
有些攔截器,例如一些調試日誌的攔截器,通常情況下都是關閉的,只有在出現問題的時候才需要打開。爲了保證網關的高可用,網關層必須具備在線啓用或關閉攔截器的能力。一般,網關需要提供restful接口方式,來關閉和啓用一個攔截器。類似這樣的命令:PUT /apigateway/v1/filters/filterName?enable=value

5、API管理與動態發佈設計
對服務管理來說,分爲前端服務管理與後端服務管理。前端服務指的是網關層暴露給客戶端使用的服務API,後端服務指的是服務層提供的業務服務API。一個服務暴露給客戶端使用,除了網關層和服務層提供服務的代碼外,還需要配置前端服務與後端服務的映射關係。
網關層API調用服務層API,有多種方式。例如,可以由按照服務層API的服務契約,生成一段客戶端代碼,發佈給網關層使用。這種方式的弊端是,網關層代碼依賴於服務層代碼,服務層頻繁修改和調整接口時,導致網關層的代碼很難維護。
可以通過配置前後端服務映射的方式,解耦網關層對服務層的依賴。當服務層的API(例如服務名、參數名等)發生變化時,只需調整映射關係,無需對網關層的代碼進行調整。網關層按照映射,自動裝配服務層API所需要的數據格式。這樣,網關層團隊與服務層團隊可以相互不受干擾地開發各自的服務。

3. 優缺點介紹

3.1 優點
(1)解耦作用:它封裝了應用的內部結構,客戶端直接和網關通信,而不必調用特定的服務。
(2)提供給每種客戶端特定優化的API。
(3)減少請求環路、簡化客戶端邏輯。比如說,API Gateway使得客戶端用一次請求就可以從多個service處獲取數據。

3.2 缺點
(1)必須被開發、部署和管理成一個高度可用的組件,也有成爲開發瓶頸的危險。
(2)爲了暴露出每個微服務的,開發者必須更新API網關。
(3)Partner OpenAPI:
轉發路由作用:對外提供的接口服務,一般直接把請求轉發到合適的service,但是此時的API GW需要增加配額、限流、令牌等一系列安全管控功能。對外提供隔離作用:請求路由,安全認證,負載均衡,限流、監控、權限控制等等。

4. 業界常用的API網關方案

通常情況下, API 網關要做很多工作,它作爲一個系統的後端總入口,承載着所有服務的組合路由轉換等工作,除此之外,我們一般也會把安全,限流,緩存,日誌,監控,重試,熔斷等放到 API 網關來做,那麼可以試想在高併發的情況下,這裏可能會出現一個性能瓶頸。
另外,如果沒有開源項目的支撐前提下,自己來做這樣一套東西,是非常大的一個工作量,而且還要做 API 網關本身的高可用等,如果一旦做不好,有可能最先掛掉的不是你的其他服務,而就是這個API網關。
4.1 基於OpenResty 的 Nginx
性能和高可用性
Nginx性能極高,Nginx先天的事件驅動型設計、全異步的網絡I/O處理機制、極少的進程間切換以及許多優化設計,都使得Nginx天生善於處理高併發壓力下的互聯網請求。Nginx的穩定性也在各大網站得到驗證。官方提供的常用模塊都非常穩定,每個worker進程相對獨立,master進程在1個worker進程出錯時可以快速“拉起”新的worker子進程提供服務。支持熱部署,可以不停機更新配置文件、更新日誌文件、更新服務器程序版本。

擴展性上
Nginx的設計極具擴展性,它完全是由多個不同功能、不同層次、不同類型且耦合度極低的模塊組成。因此,當對某一個模塊修復Bug或進行升級時,可以專注於模塊自身,無須在意其他

易用性上
Nginx使用最自由的BSD許可協議,允許用戶在自己的項目中直接使用或修改Nginx源碼,有大量的插件可以利用。但是,Nginx模塊需要用C開發,而且必須符合一系列複雜的規則。雖然通過第三方模塊,可以支持Nginx與Perl、Lua等腳本語言集成工作,但對使用者的要求還是很高。

4.2 Spring Cloud Zuul

 

基本功能
驗證與安全保障: 識別面向各類資源的驗證要求並拒絕那些與要求不符的請求。
審查與監控: 在邊緣位置追蹤有意義數據及統計結果,從而爲我們帶來準確的生產狀態結論。
動態路由: 以動態方式根據需要將請求路由至不同後端集羣處。
壓力測試: 逐漸增加指向集羣的負載流量,從而計算性能水平。
負載分配: 爲每一種負載類型分配對應容量,並棄用超出限定值的請求。
靜態響應處理: 在邊緣位置直接建立部分響應,從而避免其流入內部集羣。
Netflix公司還利用Zuul的功能通過金絲雀版本實現精確路由與壓力測試。
雖然提供的功能還算豐富,但都比較弱,很難滿足高要求的場景。

性能和高可用性
Zuul處理每個請求的方式是針對每個請求是用一個線程來處理。通常情況下,爲了提高性能,所有請求會被放到處理隊列中,從線程池中選取空閒線程來處理該請求。2016年底,Netflix將它們的網關服務Zuul進行了升級,全新的Zuul 2將HTTP請求的處理方式從同步變成了異步,以提升其處理性能。除了Netflix公司,目前Zuul在企業中用的還比較少,性能和穩定性方面還有待進一步觀察。

擴展性上
從Zuul的架構圖上可以看出,Zuul更像是一個過濾器框架,其自身的路由、日誌、反向代理、ddos預防等功能都是通過過濾器實現的。提供了PRE、ROUTING、POST和ERROR四個擴展點,可以很容易的添加自定義的過濾器。

易用性上
Zuul的搭建非常簡便,使用和配置也很簡單。Zuul的開源社區比較活躍,一直在更新狀態,但版本不算太穩定,在使用的過程中,還有一些坑要踩。例如重定向問題、異常處理問題,還沒有解決的很好,需要自己重寫一些filter。

4.3 Mashape Kong

 

Kong的一個非常誘人的地方就是提供了大量的插件來擴展應用,通過設置不同的插件可以爲服務提供各種增強的功能。Kong默認插件插件包括:

身份認證
Kong提供了Basic Authentication、Key authentication、OAuth2.0 authentication、HMAC authentication、JWT、LDAP authentication認證實現。

安全
ACL(訪問控制)、CORS(跨域資源共享)、動態SSL、IP限制、爬蟲檢測實現。

流量控制
請求限流(基於請求計數限流)、上游響應限流(根據upstream響應計數限流)、請求大小限制。限流支持本地、Redis和集羣限流模式。

分析監控
Galileo(記錄請求和響應數據,實現API分析)、Datadog(記錄API Metric如請求次數、請求大小、響應狀態和延遲,可視化API Metric)、Runscope(記錄請求和響應數據,實現API性能測試和監控)。

請求轉換、響應轉換
Kong本身也是基於Nginx的,所以在性能和穩定性上都沒有問題。Kong作爲一款商業軟件,在Nginx上做了很擴展工作,而且還有很多付費的商業插件。Kong本身也有付費的企業版,其中包括技術支持、使用培訓服務以及 API 分析插件。
從對上面三種方案的比較中可以看到,Spring Cloud Zuul非常適合創業初期的團隊,快速搭建一個“基本可用”的API網關。Nginx適合有較強研發團隊,自主開發企業自己的API網關。Kong適合於沒有自身研發團隊,但需要擁有企業級API網關能力的公司。

五、參考文章

    1. https://mp.weixin.qq.com/s/YOxX65s-eaXTWW8eSwvaZQ
    2. https://mp.weixin.qq.com/s/LRQaFbwk1UOuOQPYwu2Ovw
    3. https://mp.weixin.qq.com/s/nbtniSjr06rfboiYaW0IsQ
    4. https://mp.weixin.qq.com/s/SUt-mFYSkNHx6QA2UkNW1w
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章