用 1 個程序實現所有的功能,這是一個單體( monolithic )應用。運行程序,所有的功能都屬于同一個進程,它們之間的調用屬于進程內通信。這就保證功能模塊之間的同步通信,調用速度快。單體應用 可能存在 的問題包括:
- 一個進程集成了所有的功能,意味著它需要更多的系統資源。是否存在能夠提供這些資源的主機?用戶是否能夠或者愿意負擔這樣的主機?
- 修改或者升級任何功能模塊,必須先停止運行整個應用,導致應用暫時不可用。用戶是否接受這一點?
把所有的功能劃分為 n 個部分,分別用 1 個程序實現,這就是一個多體應用。多體應用既可以部署在單機上,也可以部署在多機上。
借用 Kubernetes 的概念,稱單機多體應用為一個 pod 。組成 pod 的多個程序運行在同一臺主機上,它們之間的調用屬于單機進程間通信,仍然是一種同步通信,調用速度也比較快。單機多體應用 有可能實現 單獨升級某一實體,其它實體繼續提供服務。但是,把多體應用部署在單機上,仍然需要考慮單機能否提供運行應用所需的系統資源。
把多體應用分別部署在多臺獨立的主機(節點)上,這是一種分布式應用。在實踐中,通常用 TCP/IP 網絡連接主機,不同節點之間只能通過消息傳遞通信。分布式應用不需要提供一個具有超強計算或存儲能力的節點,而是把所需的系統資源分布在多個普通節點上。分布式應用有可能提供高可用性和擴展性。但是,分布式應用也引入了一個魔鬼: 異步 。
首先,時鐘是異步的。每個節點都有一個物理計時器,通常是一個按照固定頻率振蕩的石英晶體。晶體在震蕩固定次數后會產生一個中斷,即一個時鐘滴答( clock tick )。節點操作系統的中斷服務程序會把存儲的時間值增加 1 。但是,不同節點的石英晶體的振蕩頻率有略微的差異。隨著時間的推移,不同i節點的當前時間值也會出現差異,即時鐘偏移( clock skew )。這意味著節點的本地時間不應視為真正的物理時間,不能依靠本地時間戳判斷全局事件的先后順序。
其次,計算是異步的。不同的節點并發地( concurrently )執行各自的程序。不同節點的失效和恢復是獨立的。這意味著一個節點的進程,不能判斷另外一個節點的進程是否已經執行完、是否已經失效。
最后,通信是異步的。傳遞的消息有可能有延遲,甚至丟失。很難區分網絡失效和節點失效。
上述三個異步,可以總結為:
- 計算:進程的執行時間沒有上限;
- 通信:消息傳遞的延遲沒有上限;
- 時鐘:本地時鐘的偏移沒有上限。
分布式應用的不同進程需要相互配合和協調,才能夠完成指定的任務。這就要求在承認異步的前提下,提供可靠的故障檢測機制、可靠的點對點通信和群組通信、可靠的數據一致性(核心點之一是定義邏輯順序)等。這正是分布式系統研究的核心內容。
再看微服務( microservice )的概念。首先,「微」意味著要拆分所有的功能,且分得相對較小,再實現為對應的程序;其次,「服務」意味著這個程序有多個(種)消費者,這些消費者的編程語言、框架和支撐系統不盡相同。這就要求提供標準化的命名和發現機制、訪問協議和交換數據格式。像現在流行的一種實現方式,是以 RESTful 風格 API 形式提供微服務,用 DNS 作為服務命名和發現機制, HTTP(S) 作為訪問協議, JSON 作為數據格式。
總之,忘掉 monolithic 和 microservice 吧。我們需要考慮下列問題:
- 要不要拆分功能,拆分的粒度多大?
- 拆分后的不同組件,是部署在單機上還是多機上?
- 其中的一些組件,需要為多個(種)消費者提供服務嗎?
本文由用戶
jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!