本文由 Shaw 發表在 ScalaCool 團隊部落格。
1.2.3 水平架構
在開發 Web 應用的時候,一些必須要考慮到的基本因素將會對程式的操作方式產生深遠的影響。但不幸的是,大多數應用程式在開發之前都不會去考慮程式碼在生產環境釋出和部署之後會發生什麼。這可能會給程式造成很大的侷限性,比如我們現在需要在多臺伺服器上執行這個程式,但如果該應用程式在設計之初就沒有考慮到這種情況,那麼讓她在此種操作模式下執行是不太實際的,除非我們對程式碼進行大面積的改動。
在接下來的討論中,我們將會認識一些部署模型並且會思考她們的優缺點。我們還將看到一種被稱作為「水平部署模型」的優勢,這一模型已經被響應式應用支援並使用了。
單點部署
單點部署是一種非常常見的部署模型,應用程式通常被部署在一臺計算機上面,通常資料庫也部署在這臺計算機上面,如下圖所示:
此部署模型由於其相對簡單而被廣泛使用,但是她有很嚴重的侷限性。當伺服器上的負載超過其閾值時,或者當機器掛了,或者應用程式升級需要安裝的時候,將會導致一個無法避免的結果——應用程式不可用。這種模型所能處理的負載很大程度上取決於硬體——當需要更好的效能時,就需要更強大的計算機,更大的記憶體以及更快的 CPU。這種通過切換更高效能的硬體來達到增加單個伺服器負載的過程稱為「垂直擴充套件」。
克隆式部署
對於那些需要更好的效能以及可用性的程式,這裡提供了一個如圖所示的比較流行的設定,這種設定涉及到了跨兩臺計算機的資料備份。
在這種設定下,資料庫和服務端的狀態都需要進行備份,對於服務端的狀態,比如,服務端使用者 session 或者快取,就可以使用 Tomcat 的叢集功能 或者其他類似的功能來進行備份。在資料庫層面,可以採用「主主同步」的方式進行備份。
這種方式使得我們可以去逐個更新部署,當程式升級的時候我們也能保證服務能正常進行。但是,當需要備份多個資料的時候,正確配置這種設定的複雜性將會大大提高。
在開發這種模式下的應用程式時,如果從開發人員的角度來看,程式仍然好像是在單個計算機上執行一樣,並且由底層框架或應用程式伺服器負責備份伺服器端的狀態。
儘管這種模式有一些優點,但是我們看到,多機設定的固有複雜性並沒有被消除,反而又增加了程式服務端的複雜性。與處理程式本身的錯誤相比較,要優雅地(為了不給客戶帶來困擾)去處理服務端的錯誤狀態更加困難,因為錯誤發生在不同的層級上面,並且服務端的狀態也並不是應用程式最需要關注的點。
水平部署
在水平架構中,如下圖所示,同一個 Web 應用程式被部署到了多個節點上面。
這些節點可能是計算機或者虛擬機器,但都有一個重要的特點就是彼此互不瞭解,並且也不共享任何狀態。這種“非共享”的原則就是「無狀態」架構的核心。
這些節點都是獨立的,其中某一個的缺失或者存在都不會以任何方式影響其他節點(除了負載增加或減少時可能會有影響,當然這取決於流量的大小)。這種架構的優點是,只需要通過向前端路由器新增新節點,可以很容易地擴充套件應用程式。
在這種模式下,我們也能實現滾動更新節點,首先將帶有新版本應用程式的新節點引入進來,然後將路由層切換一下使其指向新的節點,這樣就完成了更新。這種被稱作為「熱部署」的機制很很受“平臺即服務”(PaaS)供應商們的歡迎,比如 Heroku。
在儲存方面,與無共享的 web 應用程式相對應的是一種支援某種叢集形式的儲存技術。如 MongoDB、Cassandra、Couchbase 以及新版本的關係型資料庫(如 WebScaleSQL),這些 NoSQL 型的資料庫非常適合這種可擴充套件的前端層。
使用水平架構的一個結果是使用者可以通過路由層隨機連線到其中一個前端節點,而不是總是在同一個節點上。由於節點之間不存在共享狀態,因此無法使用伺服器端 session (Servlet 標準以及基於 Servlet 標準而構建的框架中預設存在的)。 Play 框架的核心是「無共享」,並提供了基於 cookie 的客戶端使用者 session,這點我們將在第 8 章中討論。
由於 Play! 所佔用的記憶體很小,所以在通過 PaaS 或其他雲平臺進行多點部署時,Play! 將會是一個理想的選擇,因為這些部署平臺中單個節點的可用記憶體要遠遠低於一臺專用伺服器。