摘要:流行的社交應(yīng)用Timehop(時(shí)光機(jī))能幫助人們回憶起過去某天自己在不同社交媒體上的足跡,自上線以來用戶規(guī)模不斷擴(kuò)大。Timehop的開發(fā)平臺經(jīng)歷了從Rails遷移到Go的轉(zhuǎn)變,這其中有什么原因呢?
去年,Express.js庫作者TJ Holowaychuk由Node.js轉(zhuǎn)向Go語言,并發(fā)表一篇文章,對這兩門語言進(jìn)行了對比。現(xiàn)在,又有越來越多的平臺轉(zhuǎn)向Go進(jìn)行開發(fā),例如,CSDN研發(fā)頻道去年發(fā)表的Bowery為什么放棄Node.js,轉(zhuǎn)向Go?那么,此次Timehop又為什么放棄Rails,轉(zhuǎn)向Go呢?
以下為相關(guān)譯文:
流行的社交應(yīng)用Timehop(時(shí)光機(jī))能幫助人們回憶起過去某天自己在不同社交媒體上的足跡,自上線以來用戶規(guī)模不斷擴(kuò)大。Timehop的開發(fā)平臺經(jīng)歷了從Rails遷移到Go的轉(zhuǎn)變,這其中有什么原因呢?
自把Timehop遷移到Go已經(jīng)差不多一年半了,其中95%的請求的響應(yīng)時(shí)間從Rails時(shí)代的700ms減少到70ms,每天活躍用戶數(shù)為600萬。接下來我會總結(jié)本次Go遷移過程中的體會與心得,希望能讓大家更好地認(rèn)識Go語言。
為什么選擇Go?
運(yùn)作初期,Timehop是運(yùn)行在Rails之上的。但隨著用戶數(shù)和訪問量的快速增長,Rails漸漸地出現(xiàn)了瓶頸問題。我們很多請求都是需要并行處理的。當(dāng)用戶啟動Timehop后,我們需要收集用戶在過去的全部社交數(shù)據(jù)。而不同平臺的數(shù)據(jù)查詢都是相互獨(dú)立的,所以并行處理是高頻事件。我們也曾試圖與Ruby相結(jié)合來做,但效果不理想,因?yàn)镽uby不是真正的多線程處理系統(tǒng)。
有鑒于此,我們列出了三個新平臺需要解決的問題:
能便捷進(jìn)行并行處理
真正的多線程系統(tǒng)
高性能
為什么Go能脫穎而出?
除了Ruby,Node.js也曾經(jīng)進(jìn)入我們的視野。但終我們堅(jiān)定選擇了Go:
性能: Go代碼會被編譯為機(jī)器代碼,編譯后的程序運(yùn)行速度可與C/C++媲美,并且無需額外的虛擬機(jī)和解析器;
靜態(tài)編寫:計(jì)算機(jī)能掌握所有的編寫錯誤而我們不能。為什么不依賴計(jì)算機(jī)來處理呢?
穩(wěn)健直接的并行處理:Go程序和管道使得并行代碼可讀性高、條理清晰。同時(shí)也使并行代碼更加安全而無須顯式鎖,此外也不用擔(dān)心出現(xiàn)回調(diào)錯亂。
隨著遷移工作的進(jìn)行,我們還發(fā)現(xiàn)了更多的優(yōu)點(diǎn):
十分簡便的部署工作——編譯Go程序時(shí),程序本身及所有程序依賴都會被統(tǒng)一編譯為單一個二進(jìn)制文件;
豐富的配套工具——例如代碼格式工具“go fmt”,能幫助開發(fā)者消除代碼格式不統(tǒng)一的問題。此外Go還有很多強(qiáng)大的工具;
豐富的標(biāo)準(zhǔn)庫——使用Go后,很多第三的庫都不再需要了。
可見Go十分符合我們之前提出的三點(diǎn)要求,所以我們后選擇了它。但同時(shí),團(tuán)隊(duì)里也曾就Go語言進(jìn)行過討論,現(xiàn)整理如下。
使用Go后會出現(xiàn)意外嗎?
遷移時(shí)我們怕的是影響程序代碼的生產(chǎn)力。之前使用Ruby編碼時(shí),速度是非常快的。但是使用之后,發(fā)現(xiàn)Go不但沒有影響編寫速度,同時(shí)更加穩(wěn)健,能幫助減少很多輸入錯誤。編譯速度也令人滿意,我們大的一個Go項(xiàng)目至多用時(shí)2.5s就能完成。
如何完成團(tuán)隊(duì)的技術(shù)切換?
結(jié)合個人體會,我發(fā)表過一篇入門文章供團(tuán)隊(duì)閱讀。此外,Go教程,高效Go,Go官網(wǎng)的標(biāo)準(zhǔn)庫都是很好的教材。
Go有弱點(diǎn)?
對程序依賴的管理。Go提供了一個便捷的導(dǎo)入方法,能以基于路徑的方式進(jìn)行包導(dǎo)入。例如:
import “github.com/timehop/golog/log”
你可以使用go get命令來運(yùn)行。但雖然是方便,如果有其它人改變了路徑或提供的API出現(xiàn)變更,那么可能會造成未知的部署錯誤。因此我們建議使用部署工具Godep來對程序依賴進(jìn)行管理。
部署時(shí)有哪些關(guān)鍵的庫需要注意?
我們曾試圖搜索Go on Rails的信息,但一無所獲。目前,我們使用得多的是標(biāo)準(zhǔn)net/http庫,以及Gorilla的mux。這也是目前主流的處理方式。
如何進(jìn)行托管?如何進(jìn)行部署?
剛開始是托管在與Rails相同的Heroku之上,使用Go buildback進(jìn)行部署。后來遷移到EC2,部署工作也一樣輕松。一如前述,Go程序終都是一個編譯好的二進(jìn)制文件。
我們目前的流程是:
1. 把代碼上傳到Github;
2. 使用Travis進(jìn)行測試;
3. 如果通過,進(jìn)行編譯,壓縮,然后上傳到S3。
進(jìn)行部署時(shí),從S3下載tar文件,解壓縮,然后運(yùn)行。(使用的是Chef)
能使用Go語言創(chuàng)建APIs嗎?
可以的。比方說,一個User結(jié)構(gòu)體:
type User struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Password string `json:"-"`
}
用戶信息項(xiàng)之后的標(biāo)簽定義了如何進(jìn)行JSON序列化。
如果要輸出一個用戶實(shí)例,可以簡單地編寫為:
u := User{FirstName: "Abe", LastName: "Dino", Password: "p4ssw0rd"}
jsonBytes, _ := json.Marshal(u)
Go程序在多態(tài)性和模塊化方面是如何處理的?
Go不是面向?qū)ο蟮恼Z言,沒有任何的類型分層。同時(shí)不存在繼承,能自由地進(jìn)行進(jìn)行類包含,從而實(shí)現(xiàn)多態(tài)和代碼復(fù)用。
另外Go的界面是非常友好的。不同于其它語言需要顯式地進(jìn)行類聲明,在Go中一個簡單的結(jié)構(gòu)體就可以了。我們覺得這是它強(qiáng)大的特性之一,具體原因可以參考這里。
Google的支援有多重要?
能持續(xù)得到Google的幫助與投入,對于Go語言無疑是一大福音。其社區(qū)規(guī)模也不斷擴(kuò)大,從而出現(xiàn)了很多高質(zhì)素的開源項(xiàng)目與參考資源。
寫在后
我們希望本文對Go語言感興趣的團(tuán)隊(duì)有所幫助。要想很好地使用新平臺是需要下一番功夫的,不妨與團(tuán)隊(duì)成員一起多做多思考多討論,從而確保項(xiàng)目順利進(jìn)行。
英文來自:Medium
本站文章版權(quán)歸原作者及原出處所有 。內(nèi)容為作者個人觀點(diǎn), 并不代表本站贊同其觀點(diǎn)和對其真實(shí)性負(fù)責(zé),本站只提供參考并不構(gòu)成任何投資及應(yīng)用建議。本站是一個個人學(xué)習(xí)交流的平臺,網(wǎng)站上部分文章為轉(zhuǎn)載,并不用于任何商業(yè)目的,我們已經(jīng)盡可能的對作者和來源進(jìn)行了通告,但是能力有限或疏忽,造成漏登,請及時(shí)聯(lián)系我們,我們將根據(jù)著作權(quán)人的要求,立即更正或者刪除有關(guān)內(nèi)容。本站擁有對此聲明的最終解釋權(quán)。