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