《為了更好的支持微服務,我們從PHP遷移到了Go》要點:
本文介紹了為了更好的支持微服務,我們從PHP遷移到了Go,希望對您有用。如果有疑問,可以聯(lián)系我們。
起初,我們認為堅持一門熟悉的語言是負責任的事情——我們是一個小團隊,卻已經(jīng)冒了兩次險:切換到微服務和完全重寫我們的 Web 應用程序(高流量游戲平臺).
但是,最終我們決定放棄 PHP 擁抱 Go,下面我將解釋為什么這么做,并分享一些在我們的微服務架構中數(shù)據(jù)庫相關的想法.
我們熟悉的語言是 PHP,它支撐了我們現(xiàn)有的應用程序,有兩個模糊的論據(jù)可以支持我們繼續(xù)這么做下去:
這聽起來非常合理,但是當我們清楚 PHP 真的不是我們的正確選擇時,我們很快就放棄了這些想法.
我們正在遷移到微服務架構,因為我們希望我們的高流量架構基礎設施(200 萬日活用戶)可更好擴展.從長遠來看,隨著我們向 1000 萬(還會更多)日活用戶邁進,而且每天和每小時都能隨之改變(譯者注:指擴容和縮容):隨著整個國家在休息或者白天,我們的基礎設施應該隨之彈性伸縮到相應的規(guī)模.
PHP 不適合我們的主要原因:
PHP 曾經(jīng)被設計成(或長成)為運行短命令的腳本,因此持久并不是這個語言適合支持的特性.這意味著對于每個請求,數(shù)據(jù)庫連接和類都必須重新被實例化,這增加了不必要的延遲開銷.
當然熟悉這方面讀者都知道,有解決方案,例如通過 PHP-FPM 或 Apache 的連接池或 C 綁定等方法,可以支持與 Redis 的持久連接.
但是,由于我們追求高性能,這些依賴使我們對選擇 PHP 作為合適的工具存在疑慮.
PHP 需要 Nginx 和 PHP-FPM(或類似工具)來實現(xiàn)進程和連接池管理等功能.這意味著對于每個部署的微服務,PHP-FPM 和 Nginx 也必須一起運行.這浪費了資源,也降低了擴展的效率.
還有優(yōu)化配置的問題.優(yōu)化單 PHP 實例已經(jīng)很頭大了,因為需要了解和配置 PHP,PHP-FPM 和 Nginx 這一堆組合,我們無法想象最終在彈性的 Kubernetes 環(huán)境中配置多個 PHP 棧的痛苦情形,您完全不知道在同一臺機器上運行了哪些服務.
微服務器的復雜性在架構中:您正在處理一個由簡單服務組成并且相互之間作用的復雜系統(tǒng).既然我們已經(jīng)致力于這個架構,那么因為語言而增加更多長期開銷和概念上的錯誤就是得不償失的.
招聘又如何呢?我們發(fā)現(xiàn)它對我們的情況是無效的.像微服務一樣,我們認為開發(fā)人員應該是語言無關的.我們寧愿聘請一位聰明的開發(fā)人員學習一門新語言來完成工作,而不是使用一位堅持自己做事方式的語言專家.在這個意義上,移除 PHP 實際上讓我們獲得了真正自由.
我們偏愛的兩個主要語言是 Node.js 和 Golang.我們做了一些研究,并決定了轉向 Go 而非 Node.
為什么是 Go?
性能.二進制文件的方式啟動一個長期運行的守護進程,意味著每個請求和持續(xù)連接的啟動成本很低.Go(包括 Goroutine )天生就為網(wǎng)絡及多核環(huán)境設計,使其在處理大量并發(fā)請求方面超快和高效.
Go 可以編譯成小巧且可移植的二進制文件.這使它非常適合在 Docker 容器中使用.部署我們的 Go 容器只需幾秒鐘,因為它們的體積小(大多只有 4 – 5MB),并且由于靜態(tài)鏈接的原因,在容器內(nèi)不需要 OS 或運行時依賴.作為參考,當使用 Node alpine 鏡像時,我們的前端容器大約需要 55MB.
Go 是類型嚴格的.這使代碼中的內(nèi)部通信更為可靠.它也有助于在編譯構建期間捕獲問題,而不是在運行期間.
Go 有非常好的工具鏈.雖然工具是很多語言的問題,但 Google 決定從一開始就解決這個問題,提供了大量常用的工具,作為語言安裝包的一部分.
當然我們也同時考慮到了 Go 的這些缺點:
然而,我們選擇接受這一點:使用 Go 確實需要一些努力,但它會產(chǎn)出高質(zhì)量代碼.
這不是說我們把 Go 用到所有地方.對于服務器端渲染,我們選擇 Node,因為它允許我們在前端和后端之間共享邏輯.我們也使用 Java 來解決特定的問題,因為 Java 已經(jīng)存在了很長時間,并且有大量類庫.
我們希望使用每個場景最適合的工具,也就是說,對于大多數(shù)情況,Go 將是我們的首選工具.
當我們開始用 Go 編寫我們的第一個服務時,我們同時也同時思考數(shù)據(jù)庫的問題.我們習慣使用 MySQL,它過去工作良好,但它往往也是性能瓶頸.
在我們的傳統(tǒng)技術棧中,我們還大量使用了 Redis 進行緩存,這對于性能來說非常棒,因為它有效地減少了數(shù)據(jù)庫 join 查詢的訪問壓力.
因此當我們開始在新技術棧中進行數(shù)據(jù)庫選型時,評估 NoSQL 就很有必要,可以看看我們是否可以完全避免這些 join 查詢.
我們評估了兩個數(shù)據(jù)庫:
MongoDB?– 我們很好奇去了解一個文檔型數(shù)據(jù)庫是否可以用來存儲游戲中大量元數(shù)據(jù).當然麻煩的是,我們必須在 Google Cloud 中使用,根據(jù)社區(qū)的說法,這樣根本不能很好地擴展.我們盡量避免復雜的 DevOps 工作,因此 MongoDB 出局.
Cassandra?– 它是一個已知的可以擴展的數(shù)據(jù)庫,并被一些大型高訪問量平臺 Netflix 和 Reddit 使用.我們喜歡的特性是:它的速度非常快,并支持線性擴展.不過,我們發(fā)現(xiàn)管理太復雜了.
如果您確切知道如何查詢您的數(shù)據(jù),Cassandra 非常適合.對于具有大量數(shù)據(jù)的分析服務來說,情況可能如此,但是在敏捷的產(chǎn)品設計開發(fā)環(huán)境中,隨著產(chǎn)品的發(fā)展,用戶適應性變化,Cassandra 雖然強大,但是對于我們這樣的小團隊來說難于控制.
我們逐漸走近微型服務的概念,更加堅信構建小型的獨立服務的想法,這些服務完成特定任務,并且在需要時可以輕松升級或被更換.
因此我們還是堅持使用 MySQL 作為我們的默認數(shù)據(jù)庫.我們使用了 MySQL 很多年,知道如何設計高性能的數(shù)據(jù)庫模式.雖然它不支持原生的線性伸縮,但現(xiàn)在也不是一個大的問題:由于微服務架構的模塊化特性,應用程序負載分布在許多機器的不同微服務上.并且每個微服務器都可以訪問自己的 32 核數(shù)據(jù)庫機器和幾個只讀從庫,這種方式還可以繼續(xù)前行很長的路.
我們非常高興,現(xiàn)在我們現(xiàn)在還沒有過度工程化.如果有一個服務需要 Cassandra 或其他數(shù)據(jù)庫,那么我們也可以輕松遷移該服務.
那么為什么選擇 MySQL?現(xiàn)在主要是因為它可以很方便在 Google Cloud 上進行管理,在 DevOps 方面我們是務實的.
我們也考慮嘗試 Postgres,因為它開放源碼,還有一個強大的社區(qū),并且顯然已經(jīng)運行了很多年.因此,取決于 Google Cloud 未來的 Alpha 版本,我們也可能會嘗試 Postgres.
作者補充:
Reddit 上不少網(wǎng)友指出,我們對 PHP 啟動成本有誤解.雖然我們的觀點仍然站得住腳,但為了準確起見,我們已經(jīng)清理了這一段.
另外感謝 Casper van Wezel 對本文所做貢獻. 有問題請留言,英文好的讀者可以點擊閱讀原文跟原作者互動.
相關鏈接:
文章來自微信公眾號:高可用架構
轉載請注明本頁網(wǎng)址:
http://www.snjht.com/jiaocheng/4110.html