容器化概觀:微服務 vs. 單體架構的取捨,容器與虛擬化的差異,為什麼這門課選用 Docker 管理容器
前面的章節專注在單一台伺服器上,把 Nginx、Express、WebSocket、SQLite、HTTPS 一路串起來。這一章要換個視角,討論當系統規模擴大到需要多台伺服器協作時該怎麼組織:微服務架構、容器化,以及這些概念背後解決的問題。這一節只涵蓋容器化的基本觀念,多台容器之間怎麼協調(orchestration)、怎麼分配流量,是另一個更龐大的主題,這裡不會深入。
微服務 vs. 單體架構
微服務架構(microservice architecture)是一種由多個鬆散連接的服務組成的軟體架構。它的對照組是單體架構(monolith):整個系統集中在一個巨大的程式庫裡,例如一整個 PHP 專案,或是用 Python 的 Django 把所有功能都寫在同一個專案裡。這兩者也不是互斥的,一個單體應用程式也可以再串接一堆微服務。
兩種架構各有取捨:
- 單體架構的優點:通常只用一種語言開發,所有人在同一個程式庫裡工作,彼此很清楚對方在做什麼,程式碼衝突的機會也比較低
- 微服務架構的優點:不同服務可以用最適合的語言與框架開發,例如一個團隊寫 React、另一個團隊寫 Angular,甚至也可以用 Java 或 Groovy,只要彼此不需要直接共用程式碼
- 微服務架構的缺點:協調成本高。當每個服務都用不同語言開發、對 API 的設計想法也不同,怎麼讓這些服務之間順利溝通,就變成一個需要額外處理的問題
這種取捨跟 Netflix「自由與責任」的文化很類似:微服務給了每個團隊自由選擇技術棧的空間,但也讓每個團隊必須自己負責跟其他服務對接的責任。近年來微服務越來越受歡迎,主要是因為單一服務的邏輯更容易理解,也能讓不同專長的工程師各自負責自己熟悉的部分;但微服務終究還是需要額外的管理成本,沒有哪一種架構是萬用解答。
容器化跟虛擬化的差異
要實現微服務架構,仰賴的技術是容器化(containerization),概念上跟虛擬化(virtualization)類似,但又更進一步。虛擬化是把一整台實體伺服器切成好幾個獨立的區塊,就像前面買的 VPS(Virtual Private Server):一台實體主機被切成好幾份,每一份都是一台獨立的虛擬伺服器。
容器化則是把這個概念套用到單一服務的層級。以這門課實作的伺服器為例,目前 Node.js、Nginx、SQLite 全部跑在同一台伺服器上;如果改用容器,就可以把每個服務拆成各自獨立的容器,例如 Node.js 應用程式是一個容器,Nginx 是另一個完全獨立的容器。
這種拆分帶來一個關鍵好處:不同的容器可以在不同時間點各自更新,不會互相干擾。前面每次修改 Nginx 設定,都得重新啟動整個服務,導致網站在那幾秒鐘完全無法回應;如果 Nginx 本身是跑在容器裡的,更新時可以先更新一半的容器,讓另一半繼續正常服務,等全部更新完成後再把流量切換過去,這樣就能做到零停機(zero downtime)更新,這是軟體工程領域相對晚近才普及的概念。
容器的優勢
容器已經成為雲端運算除了虛擬化之外最核心的技術。有了容器,才可能買進一批批伺服器資源,各自跑著應用程式的一小塊,進而讓系統能夠很有效率地水平擴展。這種規模在小型專案上不容易感受到,但像 Netflix 這種規模的公司,光是網站本身就同時運行著數千個容器,資料庫也是數千個實例在同時運作;靠容器化把這一切自動化,遠比手動建立上百台 Ubuntu 伺服器、再逐一照著前面幾章的步驟設定,要有效率得多。
容器最大的特點是跟作業系統無關(OS-agnostic)。這門課目前都在 Ubuntu 上操作,但容器不在乎底層跑的是 Ubuntu、macOS、Red Hat 還是 Fedora,只要有能解析容器規格的執行層,容器就能在任何地方跑起來。這門課會使用 Docker,是目前容器管理領域最主流的工具,其他常見的選擇還有 Amazon ECS、Apache Mesos、CoreOS rkt 等。
容器的優勢可以整理成幾點:
- 輕量:只跑真正需要的那個應用程式,沒有多餘的東西
- 可攜:可以在不同作業系統之間自由搬移
- 開發體驗好:下載別人建好的容器映像檔(image),很快就能在本機跑起來
- 易於管理:跟前面實作 WebSocket 搭配資料庫時的經驗一樣,串接的元件越多,出錯的環節也越多;如果每個容器只跑一個應用程式,出問題時要排查的範圍會小很多
- 啟動快:因為容器裡只有一個應用程式,啟動速度自然比較快
- 把應用程式跟底層基礎設施解耦:這是容器最重要的價值。前面一直強調走 Ubuntu 加 Nginx 這條「standard path」,好處是能直接沿用大量現成工具;但容器讓應用程式完全不需要在乎底層基礎設施或作業系統是什麼,寫好的程式可以到處跑
複習
單體架構跟微服務架構最主要的差異是什麼?
單體架構是一個龐大、通常用單一語言開發、放在同一個程式庫裡的應用程式;微服務架構則是由多個鬆散連接的服務組成,各服務可以用不同語言開發、獨立管理。
容器化的主要優點有哪些?
容器輕量、可以跨作業系統移植、易於管理、啟動速度快,並且能把應用程式跟底層基礎設施解耦。因為每個容器只跑真正需要的應用程式,不會有多餘的負擔。
實作微服務架構時會遇到什麼挑戰?
不同服務之間的協調會變得複雜,因為每個服務可能用不同語言開發、API 設計方式也不一樣,需要額外的溝通與整合機制才能讓它們順利串接。
容器怎麼做到零停機更新?
把不同的元件拆到各自獨立的容器裡,更新時可以先更新一部分容器,讓其他容器繼續正常運作,等全部更新完成後再快速把流量切換過去,避免整個系統因為更新而停機。
容器跟傳統的虛擬化有什麼不同?
虛擬化是把一整台伺服器切分成幾個獨立區塊;容器則更進一步,把每個服務拆成獨立、輕量的單位,只跑真正需要的應用程式,因此效率更高,也更容易在不同作業系統之間移植。
小測驗
單體架構跟微服務架構最主要的差異是什麼?
單體應用程式是單一龐大的程式庫,微服務則是由多個鬆散連接的服務組成實作微服務架構時,最主要的挑戰是什麼?
協調用不同語言撰寫的服務之間的溝通容器跟傳統虛擬化有什麼不同?
容器只會執行真正需要的那個應用程式,沒有額外的負擔使用微服務架構的一個關鍵優點是什麼?
不同團隊可以各自獨立使用自己偏好的程式語言與框架此文章是 FrontendMasters 上的 Full Stack Fundamentals, v3 課程筆記
