架構設計則爲知足架構需求的質量屬性尋找適當的戰術。對如何實現特定的質量屬性感興趣。質量需求指定了軟件的響應,以實現業務目標。咱們感興趣的是設計使用設計模式、架構模式或架構策略建立設計的「戰術」。算法
是什麼使一個設計具備了可移植性,一個設計具備了高性能,而另外一個設計具有了可集成性?實現這些質量屬性依賴於基本的設計策略。咱們將對這些稱之爲「戰術」的設計決策進行分析。戰術就是影響質量屬性響應控制的設計決策。戰術集合稱爲「架構策略」。架構模式以某種方式將戰術打包在一塊兒。設計模式
系統設計是由決策集合組成。對設計師來講,每一個戰術都是一個設計選擇。例如,其中一個戰術引入了冗餘,以提升系統的可用性。這是提升可用性的一個選擇可是不是惟一選擇。服務器
咱們將每一個系統質量屬性的戰術組織爲層次形式,可是每一個層次只是爲了說明一些戰術,並且任何戰術列表都確定是不完成的。架構
1. 可用性戰術框架
恢復和修復是可用性的重要方面,爲了阻止錯誤發展成故障,至少可以把錯誤限制在必定的範圍內,從而使修復成爲可能。維持可用性的全部方法包括某種類型的冗餘,用來檢測故障的某種類型的健康監視,以及當檢測到故障時某種類型的恢復。有些狀況下,監視或恢復是自動進行的,有時須要手動。性能
咱們事項考慮錯誤檢測,而後分析錯誤恢復,最後討論錯誤預防。測試
1> 錯誤檢測線程
用於識別錯誤的3個戰術是命令/響應、心跳和異常架構設計
⑴命令/響應。一個組件發出一個命令,並但願在預約義的時間內收到一個來自審查組件的響應。能夠把該戰術用在共同負責某項任務的一組組件內。客戶機也可使用這種戰術,以確保服務器對象和到服務器的通訊路徑在指望的性能邊界內操做。能夠用一種層級形式組織「命令/響應」錯誤探測器,其中最底層的探測器對與其共享一個處理器的軟件進程發出命令,較高層的錯誤探測器對較低層的探測器發出命令。與全部進程發出命令的遠程錯誤探測器相比,這種戰術所使用的通訊帶寬更少。設計
⑵心跳。一個組件按期發出一個心跳消息,另外一個組件接收聽該信息。若是心跳失敗,則假定最初的組件失敗,並通知錯誤糾正組件。心跳還能夠傳遞數據。例如,自動櫃員機按期向服務器發送一次交易日誌。該消息不只起到心跳的做用,並且傳送了要處理的數據。
⑶異常。識別錯誤的一個方法就是遇到了異常。
命令/響應和心跳戰術在不一樣的進程中操做,異常戰術在一個進程中操做。異常處理程序一般將錯誤在語義上轉換爲能夠被處理的形式。
2> 錯誤恢復
錯誤恢復由準備恢復和修復系統兩部分組成。
⑴表決。運行在冗餘處理器上的每一個進程都具備相同的輸入,它們計算髮送給表決者的一個簡單的輸出值。若是表決者檢測到單處理器的異常行爲,那麼就停止這一行爲。表決算法能夠是「多數規則」或「首選組件「或其餘算法。該方法用於糾正算法的錯誤操做或者處理器的故障,一般用在控制系統。每一個冗餘組件的軟件能夠由不一樣的小組開發,而且在不一樣平臺上執行。稍微好一點狀況是在不一樣平臺上開發一個軟件組件,可是這樣的開發和維護費用很是昂貴。
⑵主動冗餘(熱重啓)。全部的冗餘組件都以並行的方式對事件作出響應。所以他們都處在相同的狀態。僅使用一個組件的響應,丟棄其餘組件的響應。錯誤發生時,使用該戰術的系統停機時間一般是幾毫秒,由於備份是最新的,因此恢復所須要的時間就是切換時間。
⑶被動冗餘(暖重啓/雙冗餘/三冗餘)
一個組件(主要的)對事件作出響應,並通知其餘組件(備用的)必須進行狀態更新。當錯誤發生時,在繼續提供服務前,系統必須首先確保備用狀態是最新的。該方法也用在控制系統中,一般狀況是在輸入信息經過通訊通道或傳感器到來時,若是出現故障必須從主組件切換到備用組件時使用。
⑷備件
備用件是計算平臺配置用於更換各類不一樣的故障組件。出現故障時,必須將其從新啓動爲適當的軟件配置,並對其狀態進行初始化。按期設置持久設備的系統狀態的檢查點,並記錄持久設備的全部狀態變化可以使備件設置爲適當的狀態。這一般用做備用客戶機工做站,出現故障時,用戶能夠離開。該戰術的停機時間一般是幾分鐘。
⑸Shadow操做。之前出現故障的組件能夠在短期內以「shadow模式」運行,以確保在恢復該組件前,模仿工做組件行爲。
⑹狀態再同步。主動和被動冗餘戰術要求恢復的組件在從新提供服務前更新其狀態。更新的方法取決於能夠承受的停機時間、更新的規模以及更新所要求的消息的數量。
⑺檢查點/回滾。檢查點就是記錄所建立的一致狀態,或者是按期進行,或者是對具體事件作出響應。有時系統會以一種不一樣尋常的方式出現故障,可檢測到其狀態不一致。在這種狀況下,應該使用上一個一致狀態檢查點和拍了快照後所發生的事務日誌來恢復系統。
3> 錯誤預防
⑴從服務中刪除。該戰術從操做中刪除了系統的一個組件,以執行某些活動來防止預期發生的故障。一個示例就是從新啓動組件,以防止內存泄露致使故障的發生。若是從服務中刪除是自動的,則能夠設計架構策略來支持它。若是是人工進行的,則必須對系統進行設計以對其提供支持。
⑵事務。事務就是綁定幾個有序的步驟,以可以馬上撤銷整個綁定。若是進程中的一個步驟失敗的話,可使用事務來防止任何數據受到影響,還可使用事務來防止訪問相同數據的幾個同時線程之間發生衝突。
⑶進程監視器。一旦檢測到進程中存在着錯誤,監視進程就能夠刪除非執行進行,併爲該進程建立一個新的實例,就像在備件戰術中同樣,初始化爲某個適當的狀態。
總結了上面討論的戰術。
2. 可修改性戰術
可修改戰術的目標是控制實現、測試和部署變動的時間和成本。把可修改性戰術根據其目標進行分組。一組可修改性戰術目標是減小由某個變動直接影響的數量。這組稱爲「局部化修改」。另外一組可修改戰術的目標是限制對局部化的模塊的修改。這組稱爲「防止連鎖反應」。兩組之間的差異是有直接受變動影響的模塊(那些調整其責任來完成變動的模塊)間接受變動影響的模塊(那些責任保持不變,但必須改變其實現來適應直接受影響的模塊)。第三組戰術的目標是控制部署時間和成本。咱們把這組戰術叫作「延遲綁定時間」。
1> 局部化修改。
目標是在設計期間爲模塊分配責任,以把預期的變動限制在必定範圍內。其戰術有:維持語義的一致性、預期指望的變動、泛化該模塊、限制可能的選擇。
⑴維持語義的一致性。語義的一致性是在模塊中責任之間的關係。目標是確保全部這些責任都可以協同工做,不須要過多地依賴其餘模塊。該目標是經過選擇具備語義一致性的責任來實現的。耦合和內聚指標是度量語義一致性的嘗試,但它們遺漏了變動的上下文。相反根據一組預期的變動來度量語義一致性。其中一個子戰術就是「抽象通用服務」。經過專門的模塊提供通用服務一般被視爲支持重用。可是抽象通用服務也支持可修改性。若是已經抽象出了通用服務,那麼對這些通用服務的修改只須要進行一次,而不須要在使用這些服務的每一個模塊中都進行修改。此外,對使用這些服務的模塊的修改不會影響到其餘用戶。不只支持局部化修改,並且還可以防止連鎖反應。抽象通用服務的示例就是應用框架的使用和其餘中間件軟件的使用。
⑵預期指望的變動。考慮所預想的變動的集合提供了一個評估特定的責任分配的方法。基本的問題是「對於每次變動,所建議的分解是否限定了爲完成變動所須要修改的模塊的集合?」一個相關的問題是「根本不一樣的變動會影響相同模塊嗎?」這與語義一致性有什麼不一樣呢?根據語義一致性分配責任,假按期望的變動在語義上是一致的。預測指望變動的戰術不關心模塊責任的一致性,它所關心的是使變動的影響最小。在實際中很難單獨使用該戰術,由於不可能預期全部變動。基於此緣由,咱們一般結合語義一致性來使用該戰術。
⑶泛化該模塊。使一個模塊更通用可以使它根據輸入計算更普遍的功能。能夠該輸入看做是爲該模塊定義了一種語言,這可能會如同使常數成爲輸入參數同樣簡單;也可能如同把該模塊實現爲解釋程序,並使輸入參數成爲解釋程序的語言中的程序同樣複雜。模塊越通用,越有可能經過調整語言而非修改模塊來進行請求變動。
⑷限制可能的選擇。修改(尤爲是在產品線中的修改)的範圍可能很是大,所以可能會影響不少模塊。限制可能的選擇將會下降這些修改所形成的影響。例如,產品線的某個變化點可能容許處理器的變化。將處理器變動限制爲相同家族的成員就限制了可能的選擇。
2> 防止連鎖反應。
修改所產生的一個連鎖反應就是須要改變該修改並無直接影響到的模塊。例如,改變了模塊A以完成某個特定的修改,那麼必須改變模塊B,這僅僅是由於改變了A,在某種意義上來講,是由於它依賴於模塊A。