摘要
在軟體工程領域,我們積累了大量與軟體錯誤相關的概念和技術。從基本的故障定義到各種複雜的錯誤處理策略,如故障排除、容錯機制等,這些方法無疑對提高軟體的可靠性起到了重要作用。然而,這些手段是否已經足夠?我們是否已經全面探索了軟體工程中關於錯誤和可靠性的所有知識領域?
本文介紹一個新的概念——軟體系統反脆弱性,旨在從根本上改進我們處理軟體錯誤和提升可靠性的方法。反脆弱性這一概念源於反脆弱理論。反脆弱性指的是系統在面臨壓力、錯誤或混亂時,能夠不僅不會退化,反而變得更加健壯。與傳統的抗脆弱性理念不同,反脆弱性強調在不斷的挑戰中成長和改進。
1 引言
軟體工程中涉及軟體錯誤和可靠性的知識體系涵蓋了許多概念,從經典的故障、錯誤和失敗定義開始,擴充套件到故障證明、故障移除、故障容錯等技術。然而,這些手段是否已經足夠?我們是否已經全面探索了所有與錯誤相關的軟體工程概念?本文提出了一個新穎的概念——“軟體反脆弱性”,它有潛力從根本上改變我們對軟體錯誤的理解以及我們設計軟體可靠性的方法。
反脆弱性這一概念源於納西姆·尼古拉斯·塔勒布(Nassim Nicholas Taleb)在其著作《反脆弱》(Antifragile)中提出的理論。反脆弱性指的是系統在面對錯誤或壓力時,能夠不僅保持穩定,甚至變得更加強大和健壯。塔勒布對錯誤的定義非常廣泛,包括波動(如金融系統中的波動)、攻擊和衝擊(如免疫系統中的挑戰)、死亡(如人類系統中的致命事件)等。然而,塔勒布的觀點與工程實踐之間尚需建立實際的聯絡,本論文為此提供了初步探索,並討論了傳統軟體工程概念與反脆弱性之間的聯絡。
首先,本文將探討軟體反脆弱性與經典故障容錯技術之間的關係。其次,分析反脆弱性與最新的自動軟體修復和故障注入技術之間的聯絡。最後,討論開發過程的反脆弱性與最終軟體產品反脆弱性之間的關係。本文為 Arxiv 論文的修訂版。
2 軟體反脆弱性
軟體的脆弱性有許多證據,有時被稱為 “軟體脆弱性”。例如,阿麗亞娜 5 號的首次飛行因系統中某個子元件的溢位而導致火箭徹底毀壞。在完全不同的規模下,在 Eclipse 開發環境中,一個低階可選庫的外部外掛可能會崩潰整個系統,使其無法使用(Eclipse 錯誤 334466)。軟體脆弱性似乎與規模、領域和實現技術無關。
有對抗脆弱性的方法:故障預防、故障容錯、故障移除和故障預測。軟體工程師力求可靠性。他們盡最大努力預防、檢測和修復錯誤。他們透過遵循最佳實踐來預防漏洞,透過廣泛測試和與規範進行比較來檢測漏洞,透過修復測試人員或使用者報告的錯誤並在下一個版本中釋出修復來修復漏洞。然而,儘管如此,大多數軟體仍然很脆弱。這種脆弱性有務實的解釋:缺乏教育、遺留系統中的技術債務,或編寫便宜程式碼的經濟壓力。然而,我認為原因更加根本:我們沒有正確看待錯誤。
正如塔勒布所說,反脆弱系統 “喜歡錯誤”。而軟體工程師則不然。首先,錯誤是有成本的:找出和修復漏洞耗時。其次,它們是不可預測的:幾乎無法預測何時何地發生錯誤,也無法準確估計修復的難度。軟體錯誤傳統上被認為是必須根除的瘟疫,這就是問題所在。
我們或許可以將錯誤視為我們構建系統的內在特徵,而不是單純地譴責它們。複雜系統總是有錯誤:在生物系統中,錯誤不斷髮生:DNA 對未被正確複製,細胞突變等。合理大小和複雜度的軟體系統也自然會出現錯誤,就像複雜的生物和生態系統一樣。形式化驗證和模型檢查因為系統的大小和複雜性而無法證明系統沒有錯誤。一旦承認在生產中大規模和互聯的軟體系統中軟體錯誤的必要存在,這將改變遊戲規則,呼喚新的工程原則。
2.1 故障容錯與反脆弱性
與其追求一個無錯誤的完美系統,不如採用持續檢測和應對生產環境中錯誤的工程技術,例如自我檢查軟體和故障容錯機制。自我檢查、自我測試或故障容錯並不意味著字面意義上的喜愛錯誤,但確實是向前邁出的重要一步。與其迴避錯誤,不如將錯誤作為設計的一部分,甚至允許軟體崩潰,這也是 Erlang 社群中著名的崩潰重啟的理念。這種思路代表了從容面對錯誤並加以利用的正確方向。
在塔勒布的反脆弱性理論中,關鍵在於,真正的反脆弱系統不僅能應對錯誤和衝擊,甚至能夠從中變得更強。例如,人體免疫系統就是這樣一個典型案例:它需要持續面對微生物的挑戰來保持其敏銳和強大。然而,單單自我檢測錯誤並不代表反脆弱。軟體可能能夠發現很多錯誤狀態,但這並不意味著它會因此具備檢測更多問題的能力。
對於故障容錯的討論,情況更加複雜。如果故障容錯機制是靜態的,那麼即便經歷更多的故障,也無法從中獲益,系統也不會因此具備反脆弱性。但如果故障容錯機制具備自適應能力,並且在錯誤發生時能夠進行學習和改進,那麼系統會不斷最佳化,這正是反脆弱性的重要體現。
2.2 自動執行時修復
故障移除,即透過修復錯誤來提高系統可靠性,是軟體工程中的重要手段之一。接下來,我們來探討能夠在執行時自動修復自身錯誤的軟體技術,這類技術被稱為 “自動執行時修復”(也叫 “自動恢復” 或 “自我修復”)。
自動軟體修復分為兩種型別:狀態修復和行為修復。狀態修復指的是在程式執行過程中修改程式的狀態,如暫存器、堆記憶體或棧等。例如,Demsky 和 Rinard 提出的關於資料結構修復的研究,就是一種典型的狀態修復。行為修復則是透過執行時的補丁來改變程式的行為,這些補丁可以是二進位制或原始碼級別的,並且在執行時動態生成和應用,通常不需要人為干預。例如,Locasto 等人提出的行為補丁方法,曾用於修復 C 程式碼中的錯誤。
正如前面所提到的,只要軟體系統能夠從錯誤中學習和改進,就可以認為它具備了反脆弱性。在這個意義上,自動執行時修復技術,尤其是行為修復,體現了軟體的反脆弱性,因為每次錯誤的修復都會帶來程式碼的變化和最佳化,從而使系統在應對未來錯誤時變得更強大。
2.3 生產環境中的故障注入
如果你真的喜歡錯誤,你可能會主動引入更多錯誤。在軟體工程中,這可以透過故障和失敗注入技術來實現,主動在系統中製造人工錯誤。換句話說,一個真正喜歡錯誤的軟體系統會持續地進行故障和擾動注入。這樣的做法有意義嗎?
透過不斷注入故障,一個軟體系統能夠持續鍛鍊自己的錯誤恢復能力。假如系統能夠應對這些人為注入的故障,那麼它在面對類似的真實世界問題時也可能同樣能承受住衝擊。例如,在分散式系統中,伺服器可能會崩潰或與網路斷開連線。透過故障注入工具(如 “混沌猴子”),可以隨機地讓部分伺服器崩潰,以測試系統的彈性和恢復能力。
注入故障對系統有三方面的積極影響。首先,它迫使開發者必須把錯誤恢復當作工程設計的重要一環,確保系統能夠抵禦這些注入的故障。其次,它為開發者和使用者提供了信心:如果系統能夠處理這些注入的錯誤,它很可能在面對類似的現實故障時也能應對自如。最後,監控每次故障注入後的影響可以幫助團隊更好地理解系統本身的表現以及其在真實環境中的表現。
這三方面的積極作用,實際上讓系統在生產中透過故障注入而變得更強大。這與反脆弱性核心理念一致,即 “反脆弱喜歡錯誤”。這種故障注入不僅僅讓系統變得更好,還會改變整個工程生態系統,包括設計原則以及開發者的思維方式。我將在第 3 節中詳細討論產品與開發過程的關係。
當然生產環境中的故障注入需要衡量可靠性損失的風險。工程團隊必須在故障注入可能帶來的系統可靠性損失和其對軟體改進的積極影響之間找到平衡點。準確衡量這種平衡,是反脆弱軟體工程中的一個關鍵挑戰。
雖然在生產環境中注入故障的想法不同常規,但並不新鮮。早在 1975 年,Yau 和 Cheung 提出在空中交通管制系統中插入假的幽靈飛機。如果這些幽靈飛機在與系統和操作員互動的情況下安全著陸,那麼該系統就能獲得更高的信任。近年來,Netflix 推出了著名的猴子軍團,其中不同型別的猴子會注入故障到他們的服務和資料中心。例如,混沌猴子會隨機崩潰生產伺服器,而延遲猴子則會任意調整網路的延遲。他們稱這種做法為混沌工程。如果故障注入是在特定時間進行並且完全受到控制(而不是隨時隨機注入),這種測試被稱為 GameDay 演練。
自適應執行時修復能力代表著喜歡錯誤,因為具有這種能力的軟體系統能夠從錯誤中不斷改進。故障自注入的軟體系統在生產環境中透過不斷地使用故障來提升自我恢復能力,降低處理錯誤時的損失風險,因此可以稱為反脆弱的系統。
3 反脆弱性的開發過程
軟體反脆弱性的另一個方面涉及到開發過程本身。正如前文所述,反脆弱性不僅僅體現在產品的執行時表現,也體現在軟體的開發和測試過程中。
3.1 開發過程中的反脆弱性
在開發過程中,團隊應更加註重如何增強整個流程對錯誤和失敗的容忍度。一個反脆弱的開發流程不僅能夠有效處理錯誤,還能從這些錯誤中汲取經驗,在未來變得更強大。這可以透過引入自動化測試、持續整合和持續部署(CI/CD)系統、程式碼審查等手段來實現,從而提高軟體的質量和可靠性。
例如,自動化測試和持續整合的引入讓團隊能夠儘早發現並修復錯誤。這不僅提升了軟體的整體質量,也提高了團隊的工作效率。持續整合工具能夠自動檢測程式碼中的問題,並快速執行測試,使得團隊可以更早發現潛在問題,及時修復,避免錯誤積累對專案造成更大影響。這種方式將錯誤轉化為提升開發流程和產品質量的機會,體現了反脆弱性的優勢。
3.2 開發中的故障注入
類似於生產環境中的故障注入,開發過程中的故障注入同樣能夠增強系統的反脆弱性。在開發階段注入故障,團隊可以驗證系統面對故障時的恢復能力,這使得潛在的弱點得以暴露,並且能夠在軟體上線前進行修復,從而減少風險。
這種故障注入的方式幫助團隊在模擬極端條件下評估系統的表現。例如,可以模擬資源緊缺、網路延遲等問題,提前發現系統在這些環境下可能出現的瓶頸與不足。透過提前修復,系統的穩定性與可靠性大大提高。這種方法與生產環境中的故障注入異曲同工,能夠使系統在複雜多變的真實世界場景中更加健壯與穩定,進而不斷提升其抗壓能力,體現出反脆弱性的特質。
4 結論
軟體反脆弱性這一概念突破了傳統的軟體工程思維,帶來全新的視角。在這種新的框架下,錯誤與故障不再是需要徹底消除的缺陷,反而被視為系統自我最佳化、不斷進化的契機。透過自動執行時修復、生產環境的故障注入,以及在開發階段實施故障注入,軟體工程師可以逐步打造出具備反脆弱性的系統。
總的來說,軟體反脆弱性為軟體工程帶來了全新思路,讓我們面對錯誤和故障時,不再是被動防守,而是積極進取。此理念不僅有助於提升軟體質量與穩定性,也為軟體工程未來的發展開闢了嶄新的道路。
FunTester 原創精華
- 服務端功能測試
- 效能測試專題
- Java、Groovy、Go
- 白盒、工具、爬蟲、UI 自動化
- 理論、感悟、影片