一切系統都是分佈式的

這篇文章思考有一定深度,但部分觀點恐怕有失偏頗,比如作者認爲分佈式系統中的故障沒有根本原因(There is no root cause)、查找 root cause 多半是徒勞等等。

目錄

1、擁抱故障

2、分佈式設計,本地化開發

3、數據是分佈式系統的通用語言

4、複雜系統中人的角色

以下是譯文。

物流中心

人們應該感到驚訝的並不是每天都有這麼多故障,而是每天只有這麼少故障。你不應該驚 訝於自己的系統偶爾會崩潰,而應該驚訝於它竟然能長時間不出錯地運行。— Richard Cook

2007 年 9 月,76 歲的 Jean Bookout 正在 Oklahoma 一條陌生的道路上駕駛着她的豐田 凱美瑞,她的朋友 Barbara Schwarz 坐在副駕駛的位置。突然,這輛汽車自己開始加速。Bookout 嘗試了踩剎車、拉手剎,但都不管用,汽車還是繼續加速。最後這輛車撞上了路堤 ,造成 Bookout 受傷,Schwarz 死亡。在隨後的法律程序中,豐田的律師將事故原因指向 此類事故最常見的罪魁禍首:人爲失誤(human error)。“人們有時會在開車時犯錯” ,其中一位律師宣稱。Bookout 年紀很大了,而且也不是她熟悉的路,因此造成了這場悲劇 。

然而,近期一個針對豐田的 產品可靠性測試 卻令這件事情有了一個 180 度的大轉彎:凱美瑞中的一個軟件 bug 導致的棧溢出錯誤( stack overflow error)纔是此次事故的罪魁禍首。下面兩方面原因使得這一事件非常重要:

  • 此類事故最常見的背鍋俠 —— 人爲失誤 —— 最後確認並不是造成這次事故的原因( 這個假設本身就是有問題的)
  • 這件事展示了我們如何從 一個軟件錯誤導致的小故障或(潛在更大的) 公司營收損失,無縫跨越到了 人身安全 的領域

要將這件事情往小裏說可能也容易:(目前)在某款特定車型搭載的軟件中似乎發現了一個常見 bug 。

但這件事的外延要有趣的多。考慮一下目前發展地如火如荼的自動駕駛汽車。自動駕駛消除了人爲失誤 這個背鍋俠,那我們得到的結論將是:在很多方面,自動駕駛汽車要比傳統汽車更加安全。但事實真是這樣嗎?考慮下面的情況:

  • 如果發生了完全在汽車自動駕駛系統控制之外的事將會怎樣?
  • 如果訓練汽車識別紅綠燈的數據有錯誤怎麼辦?
  • 如果 Google 地圖讓它去做一些明顯很愚蠢的事,並且這些事很危險怎麼辦?

我們已經到達了軟件開發中的一個特殊點 —— 不管是在技術上還是在社會/組織上,到 了這個點我們不再能理解、看到、或控制系統的所有組件 —— 我們的軟件正在變得越來越復 雜和分佈式。軟件行業本身已經變成一個分佈式的、複雜的系統。

我們如何開發和管理那些龐大到無法理解、複雜到無法控制、出錯方式也無法預測的系統?

擁抱故障

分佈式系統曾經只是計算機科學博士和軟件架構師的領地,受衆非常小。但現在不同了。僅僅因爲你在筆記本電腦上寫程序、無需關心消息如何傳遞和鎖問題,並不意味着你不 需要關心分佈式系統:

  • 你寫的程序發起了多少對外部服務的 API 調用?
  • 你的代碼是跑在PC 上還是移動設備上 —— 你確切地知道所有可能的設備類型嗎?
  • 當你的應用正在運行時,它可能遇到哪些網絡方面的限制,關於這些你知道多少?
  • 當軟件到達特定規模時,它會遇到哪些瓶頸,關於這些你又知道多少?

在經典分佈式計算理論中,我們學到的一件事情是:分佈式系統經常會發生故障,而且 大都是局部而非全局故障。這些故障不僅難於診斷和預測,而且很難復現 —— 可 能是某個特定的第三方數據流沒數據了,可能是位於某個你從未聽說過的地方的路由器掛掉 了。你永遠在同短時故障(intermittent failure)作鬥爭,這注定是一場失敗的戰役 嗎?

應對複雜分佈式系統的方法並不是簡單地增加測試,或者採用敏捷開發流程,也不是採用 DevOps 或者持續交付(continuous delivery)。任何單一的技術或方法都無法阻止類似 豐田汽車事故這樣的事情再次發生。實際上,類似這樣的事情肯定會再次發生。

解決這類問題我們需要擁抱這樣一種觀念:無法預知的故障種類太多了 —— 我們面對的是一 片巨大而未知的未知海洋;此外,還需要改變我們構建系統時 —— 以及運維現有系統時 —— 的思考方式。

分佈式設計,本地化開發

好了,現在我們可以確定的一點是:每個編寫或開發軟件的人都需要像分佈式系統工程師 一樣去思考。但這句話到底意味着什麼?在實際中,它意味着:丟棄那種單計算機(節點)的思考模式(single-computer mode of thinking)。

直到最近,我們纔可以將計算機視爲一個相對確定性的東西(a relatively deterministic thing)。當編寫一個在某臺機器上運行的代碼時,我們能夠確定性地假設很多東西,例如 ,內存查詢的方式。但現在已經沒有應用還運行在單臺機器上了 —— 雲就是這個時代的計 算機(the cloud is the computer now),它就像一個生命系統(living system),一 直在持續不斷地變化,尤其是在越來越多的公司開始採用持續交付這種新範式的過程中。

因此,你必須開始:

  • 接受這樣的假設:支撐你的軟件運行的系統一定會發生故障
  • 對爲什麼會發生故障以及故障可能會以怎樣的形式發生做出預案
  • 針對這些預案設計數據收集方案

這並不是像說一句“我們需要更多測試”那麼簡單。傳統的測試哲學中,假定 所有測試用例都是能夠描述出來的,但在分佈式系統中這一點不再成立。(這並不是說 測試不重要了,而是說測試不再是萬靈藥。)

當處於一個分佈式環境、並且大部分故障模 式都是無法提前預測也無法測試時,監控就成了唯一的理解應用行爲的方式。

數據是分佈式系統的通用語言

如果對剛纔的比喻(複雜系統就像一個生命系統)進行延伸,那在 診斷出一個人中風後 纔去尋找病因 與 在中風前就能及早發現問題 明顯是兩種方式。你當然可以翻閱病 例上的就診記錄,從中看出其實早有中風的苗頭,但你更需要的是一個早期告警系統, 以及一種在問題剛發生時就能看到並儘可能快地介入處理的方式。

另外, 歷史數據只能告訴你哪裏出了問題,並且是侷限在特定時間段內的問題。但在處理分佈 式系統相關的問題時,需要關心的事情要比僅僅 ping 一下服務器通不通多多了。

與測量和監控相關的工具現在已經有很多,這裏不會就具體工具展開討論,而是要告訴你:在查看自己的應用和系統的監控數據的過程中,你會對“直方圖通常比平均值更能說明問 題”有越來越深的理解,在這個過程中開發者不會再將監控視爲純粹是系統管理員的領 域。

複雜系統中人的角色

無論多麼複雜的軟件最終都是人寫出來的。

任何對分佈式系統和複雜度管理的討論最終都必須承認 人在我們設計和運行的系統中 的角色。人是我們創造出來的複雜系統中不可分割的一部分,而且很大程度上我們要對他 們的多樣性(variability )和適應性(resilience )負責(或對他們缺乏這兩種特性負 責)。

作爲複雜系統的設計者、建造者和運營者,我們受一種厭惡風險(risk-averse)文化 的影響,不管我們是否意識到這一點。在試圖(在進程、產品或大型系統中)避免故障的過 程中,爲了使自己能夠有更多“把控”(control),我們傾向於粗細不分地列出需求( exhaustive requirements)和創建緊耦合(tight couplings),但這種方式經常 更容易導致故障,或者產生更脆弱的系統。

當系統發生故障時,我們的方式是責備(blame)。我們粗魯地尋找所謂的故障“原因” —— 實際上,相比於尋找真正原因以避免將來再出現類似問題,這種所謂的尋找故障“原因”的 過程經常只是一個減輕負罪感和尋求內心平靜的活動。這類活動通常會導致人們繼續加強對 系統的“把控”,而結果是最終的系統更加脆弱。

這裏的現實是:大部分大故障都是一連串小故障疊加的結果,最終觸發了某個事件(most large failures are the result of a string of micro-failures leading up to the final event)。這些故障並沒有根本原因(There is no root cause)。我們最好不 要再去試圖尋找根本原因了,這樣做只是在攀登文化期望(cultural expectations)和強 大且根深蒂固的心理本能(psychological instincts)的懸崖峭壁。

20 世紀 80 年代奏效的流程和方法論,到了 90 年代已略顯落後,現在更是完全不適用了 。我們正在探索新的領地和模型,以構建、部署和維護軟件 —— 以及開發軟件的組織自身( organizations themselves)。

推薦

A Big Picture of Kubernetes

Kubernetes入門培訓(內含PPT)


隨手關注或者”在看“,誠摯感謝!

本文分享自微信公衆號 - 雲原生技術愛好者社區(programmer_java)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

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