【架構】21個軟件架構特點解析

作者 | sergiuoltean
策劃 | 萬佳

衆所周知,架構特點多以"ility"結尾(例如 scalability、deployability),也被稱爲 NFR(非功能需求)、質量屬性。架構的特點沒有固定清單,但標準是有的,就是 ISO25010:


我們從業務需求(業務特徵)、我們期望的系統運營方式(運營特徵)中總結出這些特點,它們是隱式的、貫穿各領域,是架構師在字裏行間能看出來的特點。《軟件架構基礎》書中的這張表是隱藏特點的一個例子。


《實踐中的軟件架構》一書中對架構特點解釋得很清楚。


刺激的來源(Source of Stiumulus)可以是角色、觸發事件的東西等。刺激(Stimulus)是實際產生的事件。環境(Environment)代表事件發生的系統條件。工件(Artifact)是系統中正在被刺激的部分。響應(Response)就是工件在我們應該度量(measure)的刺激下的行爲方式。背景瞭解完畢,讓我們來看具體的特點。

1性能

根據 Smith 所說,“性能是指響應能力:響應特定事件所需的時間,或給定時間間隔內處理的事件數”。性能可以有以下指標:

  • 延遲 。表示獲得響應之前經過的時間,這裏指的是一段時間。我們有最小延遲(開始時間)和 截止日期 (結束時間)。衡量延遲的其他因素包括 優先級(我們在其中查看響應的順序)和 抖動 (隨時間觀察到的延遲波動)。

  • 吞吐量。是指在固定時間間隔內獲得的響應數。但爲了提高精度,我們應該度量多個時間間隔。

  • 可用容量。以上度量的結合體。在不超出延遲要求的情況下可實現的最大吞吐量。

  • 可調度的利用率。利用率是資源繁忙時間的百分比,而可調度的利用率是滿足一定時間要求的最大利用率。

  • 數據丟失。如果使用緩存來提高性能,那麼緩存未命中將成爲性能指標。

 提高性能的技術

首先我們要了解影響性能的因素。

  • 需求 。我們需要多少資源?

  • 硬件 。我們需要什麼類型的資源?比如 CPU、內存、I/O 設備、網絡等。系統是否運行在正常條件下?還是在重負載下?

  • 軟件 。我們使用的框架是否是高性能的?有沒有使用緩存?是否涉及某種反射(java)?是否做了最大的優化工作?

我們需要控制需求,爲此我們可以使用隊列、節流和背壓機制。通過改進算法,我們可以減少資源需求。通過設置最大響應時間(超時)和某種優先級,我們可以進一步控制需求。

可以使用垂直縮放來獲得更好的響應時間。提高性能的另一種方法是併發。還需要注意阿姆達爾定律。


加速效果的瓶頸是程序的串行部分。例如,如果 95%的代碼可以並行化,則並行計算的理論最大加速比將是 20 倍。

限制你的資源、對所有內容(線程、隊列)實施固定的生產限制、規劃資源使用並儘可能避免爭用……這些說起來容易,做起來難。還可以充分利用緩存、水平縮放、添加多個處理單元等。

你應該瞭解你的框架和你的數據庫,並優化它們。

2可靠性

根據《牛津詞典》,可靠意味着質量或性能始終如一,且能夠被信任。可靠性可以用平均故障間隔時間(MTBF)來表示,可靠性 =exp(-t/MTBF)。

可靠性很難用數字度量。我們可以用一些軟件指標衡量複雜度和代碼覆蓋率,以瞭解可靠性的邊緣情況。適應度函數也可用於度量可靠性。未解決問題的數量、成功的構建和部署的數量也是一些可用指標。ISO-9001 是衡量可靠性的另一種方法。

https://sergiuoltean.com/2020/04/29/fitness-functions/

 提高可靠性的技術

遵循最佳工程實踐將產生更好的產品。使用更好的管理實踐和流程,可以實現更高的可靠性。突變測試技術會讓系統考慮邊緣情況。混沌測試是提高可靠性的另一個重要工具。總之我們要強化系統來提高可靠性。

3可用性

表示可用系統時間與總工作時間的比率。這是可靠性之上的另一層。它是系統掩蓋或修復特定閾值(例如時間間隔)內故障的能力。可用性可以表示爲

在公衆號互聯網架構師後臺回覆“2T”,獲取Java面試題和答案驚喜禮包。


MTBF= 平均無故障時間;MTTR= 平均修復時間

於是我們計算出下表:


 提高可用性的技術

爲了提升它,首先我們需要檢測潛在的故障。


檢測到異常情況後,我們可以進行干預。


4彈性

彈性指的是系統遇到問題時可以降級(而非中斷服務),等待問題修復完成,表示的是系統在遇到嚴重故障時的持續運行能力。爲實現彈性,需要提前設置防禦機制(斷路器模式)。彈性有時被稱爲容錯性 。彈性系統指的是可以適應壓力並持續運行的系統。很難用數字指標來度量彈性。

 增強彈性的技術

首先是確定潛在風險:系統有哪些關鍵功能?哪些硬件至關重要?然後我們需要實施保護策略,爲此需要檢查哪些事件可能導致這些重要部件發生故障。找出風險因素後就需要確定容忍閾值。具體的保護策略包括對請求數和線程數施加限制、緩存相同的請求、批量發送請求等。

5可信賴性

它包括可靠性可用性彈性可持續性 (可用性 / 彈性的比值)、可恢復性 (彈性函數)和 穩健性 (可靠性函數)。我們應該始終將它們視爲一個整體。

拿一輛汽車來說,如果它是新車並且是知名的可靠品牌(例如梅賽德斯),我們可以說它是可靠的。它有備用輪胎,所以有一些可用性。四輪驅動意味着彈性,其中兩輪出故障還有兩輪能工作(但性能會下降)。可持續性是可用性(備用輪胎)和彈性(四輪驅動)的綜合。健壯性在這裏可以指道路通過能力。如果汽車是電動的,那麼充電速度就是一個可恢復性指標。

6可伸縮性

它是系統在重負載下在可接受的閾值內的執行能力。它分爲手動和自動可伸縮性兩種,後者也叫 靈活性 。當負載突增時,系統會做出反應並水平縮放(添加 / 刪除更多實例)。我們可以查看 CPU 和內存來觀察這些突發事件。這些突發操作完成後,系統將殺死不必要的實例,從而降低成本。垂直伸縮意味着我們向系統添加了更多物理資源(例如更多的內存、更好的 cpu)。

 實現可伸縮性的技術

這裏涉及到 devops,最好使用 aws fargate 之類的雲服務。

https://aws.amazon.com/fargate/

下圖中可以看到放大和縮小策略。


7安全性

它實際上是許多特點的集合:機密性 是指系統保護用戶數據安全的能力;完整性 是保護外部資源免遭篡改的能力;身份驗證 允許用戶訪問系統;授權 則告訴用戶可以訪問系統的哪些部分。授權通常使用 RBAC、ACL 或 ABAC 來實現。不可否認性 保證了消息的發送者不能否認自己發送了消息,並且接收者也不能否認自己接收了消息。

 增強安全性的技術

首先我們需要檢測。


針對攻擊行爲,我們需要制定靈活的應對策略。大多數情況下我們可以撤消訪問權限,在某些極端情況下我們可以關閉系統,當然最好還是避免後一種情況出現。最好使用成熟的安全解決方案,自行實現往往不是好辦法。

8互操作性

它表示系統與外部系統通信的能力。合約接口是互操作性中最重要的概念,其涵蓋了通信的所有方面,包括錯誤處理。

 改善互操作性的技術

最好的策略是使用企業集成模式。如果用到多個通信協議,這種策略就是最佳方法。

https://learning.oreilly.com/library/view/enterprise-integration-patterns/0321200683/

9可調整性

也稱爲 可變性 ,其描述了系統變化的難易程度。一般來說它是一個隱含的特徵。作爲架構師,你要知道系統變化的概率是未知的,但一旦出現變化,系統應該能夠優雅地應對。變化是軟件世界中唯一確定的事物。話雖如此,我們不能將整個系統都設計爲可變組件。如果每個組件都是即插即用組件,設計就做不完了。因此我們需要找到那些變化概率很高的部分。

 改進可調整性的技術

有兩個維度。作爲一名架構師,你需要確定哪些部分具有較高的變化概率;作爲軟件工程師,你必須確保這些部分容易改動。遵循 SOLID 原則是一個很好的開始。可以使用適應度函數度量傳入和傳出耦合。我們需要計算變化成本。比如要構建一個 UI 表單,它需要的位置比我們最初想像的要多,則我們可以複製粘貼代碼並進行必要的調整,也可以構建一個新組件並插進來。然後我們得到了變化的成本:

N x 編寫代碼的成本(複製粘貼)<= 編寫組件 +(N x 將其插進來的成本)

還需要考慮時間,觀察較長的時間才能得到可靠的觀察結果。

10可部署性

所有系統都應封裝在某種工件中,可以是 war、jar、ear、apk、dll、gem 等。它們被部署在能夠運行它們的環境中。由於 docker 的進化,現在我們可以在一臺機器上擁有多個環境。可部署性是一種將代碼轉換爲客戶可用產品的機制。

 改善可部署性的技術

最有效的是實施持續集成 / 持續部署(CI/CD)。認真的話,每次代碼推送都將觸發一個生產部署。爲此,應通過適應度函數和自動化測試來保護你的代碼。它是抗脆弱性的關鍵部分。我們希望能按需部署,一鍵完成工作。我們也會部署硬件。使用基礎架構即代碼之類的技術可以提高效率。


11可測試性

在所有系統中它都是一個重要特徵。我們必須確保構建的系統尊重了客戶的需求。複雜的系統很難測試。以微服務架構爲例,我們有很多獨立開發的活動部件。這個特徵經常會讓步給其他特徵。爲了使系統可測試,我們需要能控制每個組件的輸入和輸出。

 改善可測試性的技術

請儘量控制系統的複雜性。我們應該構建較小的組件,不要重新發明輪子;還應該編寫可測試的代碼,在適當的位置應用 TDD。

12簡單性

這條特徵是很難實現的。一切都是權衡取捨,而大多數情況下這一條都會被犧牲掉。但如果我們需要在有限的時間內快速構建某些東西,那麼就應該優先考慮簡單性。在構建 MVP(最小可行產品)時,我們關心的只有簡單性。但請注意,實現目標之後,我們不應丟掉所有東西。不要與 PoC(概念驗證)或某種 R&D 混淆。可重用性 在這裏也很重要。在公衆號互聯網架構師後臺回覆“2T”,獲取一份驚喜禮包。

 改善簡單性的技術

可以構建粗粒度的組件;使用 RAD 框架,例如 ApacheIsis、Vaadin 或 JHipster;犧牲簡單性之前請確保自己能承受對應的代價;遵循 KISS 原則。記住時間是關鍵:先跑起來,再考慮美觀和性能。

13可移植性

指的是系統從一個操作系統移植到另一個的能力,它會影響編程語言的選擇。例如,我們知道爲了運行 Java 代碼需要一個 JVM,因此問題就是“JVM 是否可移植?”答案是肯定的。另一個例子是 golang:它打包爲二進制文件,不需要外部依賴項,因此是可移植的。一些微軟專屬技術就不行,它們只能運行在微軟操作系統中。

 改善可移植性的技術

一個顯而易見的選項就是容器化、docker。一個 docker 引擎能夠運行多個隱藏了實現細節的 docker 容器。

14易用性

談到易用性時通常會提到 可配置性 ,即用戶自定義系統的能力,比如通過 UI 主題更改外觀和配置系統行爲(例如控制用戶訪問權限等)。還有 本地化,也稱爲 i18n(internationalization)。它指的是系統支持多種標準的能力,一般是通過用戶體驗(UX)實現的。這裏的標準指的是語言、貨幣、公制單位、字符編碼等。本地化資源通常是靜態的。

可訪問性 是另一個易用性特徵。世界上有些人是殘疾的(失明、聽力受損、色盲),我們如何確保這些人可以受益於我們的系統呢?對於色盲來說,選擇顏色會花很多時間。Siri/Alexa 是盲人的好幫手。考慮可訪問性時,請想到我們的祖父母是不是能方便地使用我們的系統。

另外還有 可支持性 ,比如說幫助頁面或者 24x7 技術支持。我們應該努力讓系統直觀易用,這會影響可學習性,也就是用戶習慣系統所需的時間。用戶培訓和幫助頁面之類的策略很好用。

15可擴展性

它是描述系統對即插即用組件需求程度的特徵。對於使用內核架構的系統來說,這是很重要的特徵。Eclipse Platform 和 OSGI 標準就是經典的例子。

16抗脆弱性

它是系統應對壓力、衝擊、波動、噪聲、錯誤、故障或攻擊的能力。


 改善抗脆弱性的技術

首先我們要敲打敲打系統。可以使用 CI/CD,它們本來就是做這種事的。每次代碼更改都必須投入生產。當然,我們也要有防禦機制,適應度函數就是個好方法;Simian Army 也是個不錯的工具。

https://github.com/Netflix/SimianArmy

17可升級性

它是指系統無縫升級自身的能力。對於非 Web 產品(例如 App Store 和 Google Play),這很容易實現,因爲它們的升級能力是嵌入到 OS 中的;涉及到 Web 應用時,事情就麻煩多了。

 改善可升級性的技術

首先我們需要爲服務提供版本控制。下一步是使用藍綠部署或金絲雀部署等策略進行零停機的時間部署。

18合規性

不管我們需要的是哪種第三方工具和框架,都應該得到它們的合法授權。我們需要重視開源軟件的合規性因素,因爲它們可能會附帶一些我們不想要的額外約束。沒有人願意暴露自己的源代碼,因此我們應該遠離 GPL 許可證。在歐盟,《GDPR》已成爲強制規定,因此我們需要確保系統符合其規定。還要考慮一些 ISO 標準,公司可能需要遵循某些流程才能符合它們的要求。


 改善合規性的技術

理想情況下,每家公司都應該有一個法律部門,但現實並非如此。適應度函數(例如許可證檢查)可以保護我們免受列入黑名單的許可證的影響。在設計系統時,我們必須找到一種保護用戶數據隱私的方法。

19成本

可能是最重要的架構特點。一切都有成本,虛擬的、還是現實的都一樣。任何成本都可以換算成金錢。如果我們需要購買某些工具(IDE)、雲服務(例如 AWS)、第三方框架(例如 new-relic)的許可證,則總會產生財務成本。開發團隊也要發工資,學習新技術或培訓團隊成員需要花錢。不尊重敏捷宣言是有代價的;錯誤的代碼要付出代價;缺少單元測試會有代價;缺少 CI/CD 會有代價;沒有基礎架構即代碼也會有代價……這個列表是沒有盡頭的。

 降低成本的技術

幫助客戶控制成本是我們的責任。我們需要區分單純的成本和投資,並讓客戶相信投資是划算的。

以 Scrum 流程爲例,我個人認爲它沒什麼用。在一個固定的週期(通常爲兩週)中,我們有這麼多的儀式(計劃、站會、演示、回顧),然後根據(猜出來的)估計值做計算,結果 Sprint 完成度 100%只是偶然而非必然。我們需要敏捷和適應,而不是盲目地遵循流程。我們應該減少會議和儀式,這樣成本就會下降。我們應該專注於完成工作的本質要素。

測試是必要的投資,快速前進的唯一方法就是正確前進。我們必須說服客戶,從長遠來看,成本是會下降的。測試會減少錯誤的數量,從而減少成本。

代碼質量是另一項投資。好的代碼將帶來更好的測試,提高穩健性、可維護性、可調整性等。與難以維護的系統相比,我們的更改花費的時間會更少,成本會下降。

20可存檔性

指系統保留歷史數據記錄的能力。在數據是一等公民的系統中(例如財務系統),這個特徵非常重要。數據絕不會刪除,而只會歸檔,這主要是考慮到法律要求。可歸檔性是對可審計性的支持。

 實現可歸檔性的技術

首先是在數據上使用時間戳(例如 updatedOn、createdOn)。然後要有一個 cron 作業,將所有低於特定閾值的數據移入歷史表中。另一種技術是將數據標記爲軟刪除,但這會影響查詢性能。

21可審覈性 / 可跟蹤性

這是支持重構歷史的系統特徵。我們必須記錄所有關鍵操作(尤其是在安全場景中),以便重現問題並從錯誤中學習經驗。我們也可以將這些記錄用作法律依據。

 實現可審覈性的技術

記錄每個關鍵操作並集中存放這些記錄。可以使用 ELK,或 sleuth-zipkin 具。

【滴滴開源】六大企業級項目!


【IDEA插件】  EasyCode(代碼生成器)


【開源】Java身份證號碼識別系統


【推薦】Docker 圖形化管理工具:Portainer



戳這兒


本文分享自微信公衆號 - 俠夢的開發筆記(xmdevnote)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章