Cloudflare 從 PHP 到 Go:遷移與經(jīng)驗(yàn)分享
大家好,我是煎魚。
在現(xiàn)代軟件開發(fā)中,技術(shù)棧的選擇對(duì)于項(xiàng)目的成功至關(guān)重要。隨著業(yè)務(wù)需求的演變,技術(shù)遷移成為了一個(gè)不可避免的話題。
在本文中,我們將探討從 PHP 到 Go 的遷移過(guò)程。分享來(lái)自 Cloudflare 的資深工程師 Matt Boyle 和 Chris Shepherd 的見解和經(jīng)驗(yàn)。
主要內(nèi)容將涉及他們遷移的動(dòng)機(jī)、挑戰(zhàn)、以及在這個(gè)過(guò)程中的心得體會(huì)。
遷移動(dòng)機(jī)
性能考量
Matt Boyle 指出,他們開始考慮從 PHP 遷移到 Go 的一個(gè)主要原因是性能。例如:他們有一個(gè)系統(tǒng)在 PHP 中只能處理大約 10 個(gè)請(qǐng)求每秒,并且消耗了大量的 CPU 和內(nèi)存資源。
而在遷移到 Go 后,相同的系統(tǒng)能夠處理數(shù)千個(gè)請(qǐng)求每秒,同時(shí) CPU 和內(nèi)存的使用量卻大大降低。
招聘與人才吸引
Go 語(yǔ)言以其高性能和簡(jiǎn)潔性而聞名,這使得它成為吸引技術(shù)人才的一個(gè)亮點(diǎn)。
Chris Shepherd 提到,Go 語(yǔ)言的流行使得公司能夠吸引到更多對(duì)新技術(shù)有興趣的開發(fā)者,比如在柏林的初創(chuàng)公司中,Go 語(yǔ)言的開發(fā)人員需求正在增長(zhǎng)。
生態(tài)系統(tǒng)和工具鏈
Go 語(yǔ)言擁有一個(gè)強(qiáng)大的標(biāo)準(zhǔn)庫(kù)和活躍的社區(qū),這為開發(fā)者提供了豐富的工具和庫(kù)。例如,Go 的 net/http 包提供了一個(gè)強(qiáng)大的 HTTP 服務(wù)器框架,使得構(gòu)建 RESTful API 變得簡(jiǎn)單。
此外,Go 的編譯型特性使得容器化部署變得簡(jiǎn)單,相較于 PHP 的解釋型特性,Go 應(yīng)用的容器鏡像可以做得更小,這在云原生時(shí)代尤為重要。
遷移過(guò)程
逐步遷移 vs. 重寫
在遷移過(guò)程中,Matt Boyle 建議采取逐步遷移的策略,而不是完全重寫應(yīng)用。
例如,他們沒有選擇一次性將整個(gè)應(yīng)用從 PHP 重寫為 Go,而是構(gòu)建了新的 Go 服務(wù)來(lái)處理特定的業(yè)務(wù)邏輯。
同時(shí)保留 PHP 服務(wù)處理其他邏輯,這種方法被稱為 “絞殺者模式”(strangler pattern)。
絞殺者模式
數(shù)據(jù)一致性挑戰(zhàn)
Chris Shepherd 分享了一個(gè)關(guān)于數(shù)據(jù)一致性挑戰(zhàn)的故事。
在他早期的一次遷移中,一個(gè)簡(jiǎn)單的數(shù)據(jù)類型變更(將字符串類型更改為時(shí)間戳)導(dǎo)致了服務(wù)間的不一致,從而影響了用戶的數(shù)據(jù)展示。
這個(gè)故事強(qiáng)調(diào)了在分布式系統(tǒng)中保持?jǐn)?shù)據(jù)一致性的重要性。
學(xué)習(xí)曲線
兩位嘉賓都提到了從 PHP 到 Go 的學(xué)習(xí)曲線。例如,Go 語(yǔ)言的并發(fā)模型(使用 goroutines 和 channels)與 PHP 的多線程處理有很大的不同,需要時(shí)間去適應(yīng)和學(xué)習(xí)。
goroutines + channels
Chris 回憶起他最初使用 Go 時(shí),對(duì)于如何正確地使用 goroutines 和 channels 進(jìn)行并發(fā)編程感到困惑,但隨著時(shí)間的推移,他逐漸掌握了這些概念。
遷移中的挑戰(zhàn)與解決方案
分布式系統(tǒng)的復(fù)雜性
遷移到 Go 后,開發(fā)者需要面對(duì)分布式系統(tǒng)帶來(lái)的復(fù)雜性,包括網(wǎng)絡(luò)延遲、數(shù)據(jù)同步等問題。
Matt Boyle 強(qiáng)調(diào)了在遷移過(guò)程中對(duì)基礎(chǔ)設(shè)施和可觀測(cè)性的投資的重要性。
例如:Cloudflare 跟蹤了一個(gè)名為 “復(fù)制延遲” 的指標(biāo),以確保數(shù)據(jù)在不同的數(shù)據(jù)庫(kù)副本之間同步的時(shí)間差異最小化。
Replication Lag
技術(shù)債務(wù)
Chris Shepherd 提醒我們,即使是使用 Go 語(yǔ)言,技術(shù)債務(wù)也是不可避免的。新寫的 Go 服務(wù)可能并不完美,需要時(shí)間去迭代和優(yōu)化。
例如:他們最初在 Go 中實(shí)現(xiàn)的一個(gè)服務(wù)可能沒有考慮到所有的邊緣情況,導(dǎo)致在高負(fù)載下出現(xiàn)性能問題,這需要后續(xù)的優(yōu)化和重構(gòu)。
依賴管理
Go 語(yǔ)言的依賴管理曾經(jīng)是一個(gè)痛點(diǎn),但隨著 Go Modules 的引入,這一問題得到了改善。
圖片
Go Modules
Matt Boyle 回憶了過(guò)去處理 gopath 的痛苦經(jīng)歷,并對(duì)比了 Go 和 PHP 在依賴管理上的差異。
例如:PHP 的 Composer 可以輕松管理項(xiàng)目依賴,而 Go 直到 Go Modules 出現(xiàn)之前,依賴管理都是一個(gè)挑戰(zhàn)。
總結(jié)
從 PHP 到 Go 的遷移是一個(gè)復(fù)雜的過(guò)程,涉及到性能優(yōu)化、團(tuán)隊(duì)技能提升和工具鏈的更新。
通過(guò)逐步遷移、重視數(shù)據(jù)一致性和分布式系統(tǒng)的挑戰(zhàn),以及對(duì)技術(shù)債務(wù)的管理,團(tuán)隊(duì)可以更平滑地完成這一過(guò)程。
Matt Boyle 和 Chris Shepherd 的經(jīng)驗(yàn)分享為我們提供了寶貴的洞見,幫助我們理解遷移的動(dòng)機(jī)、過(guò)程和挑戰(zhàn),以及如何成功地完成這一旅程。