使用Go語(yǔ)言來(lái)提升Ruby應(yīng)用的性能
近年來(lái),Go語(yǔ)言的表現(xiàn)相當(dāng)引人注目。它與Ruby的差異明顯,Go的優(yōu)勢(shì),例如成本低廉且易用的并發(fā)性能,使得我們尋找如何使用的方法,應(yīng)用到處理工作任務(wù)中去。本文著重于闡述能夠***你在ruby應(yīng)用程序中使用Go的理由。并且會(huì)深入細(xì)節(jié),我會(huì)提供我的啟動(dòng)項(xiàng)目Firmapi的源代碼。
Go可以為ruby開(kāi)發(fā)者帶來(lái)什么
更準(zhǔn)確的說(shuō),Go可以給你的ruby代碼帶來(lái)什么
1.低成本且易用的并發(fā)
按照Go的設(shè)計(jì),幾十個(gè)(甚至上千個(gè))并發(fā)操作能夠輕而易舉的實(shí)現(xiàn)。它能夠充分利用所有CPU的優(yōu)勢(shì)。
盡管使用ruby早就可以處理線(xiàn)程操作了,但是其處理結(jié)果遠(yuǎn)比不上Go:Ruby使用的是綠色線(xiàn)程,(即只有一個(gè)CPU得到利用),這與Go的channels方式相去甚遠(yuǎn)。
2. 低內(nèi)存開(kāi)銷(xiāo)
一個(gè) Go 程序編譯出來(lái)也就幾 M 大小。他們能在***化“榨取”機(jī)器性能的同時(shí)高效的利用內(nèi)存。在 資源密集型任務(wù)中獨(dú)立的獲取輸入并返回計(jì)算結(jié)果 這類(lèi)情況中,Golang 的表現(xiàn)堪稱(chēng)***。你能輕松的啟動(dòng)的多個(gè)程序,他們只有在需要時(shí)才被喚醒,同時(shí)還能得到非常不錯(cuò)的性能。
3. 易于部署
Go 程序能在數(shù)秒內(nèi)被編譯成一個(gè)小的二進(jìn)制文件。 無(wú)需任何依賴(lài),他們就能被輕松部署到您的生產(chǎn)服務(wù)器上。稍后,我將在 Firmapi 上向您展示我們是如何將 Go 代碼部署到我們的服務(wù)器上的。
連通 Go 和 Ruby
已經(jīng)有 一個(gè) gem 被發(fā)布出來(lái),使之成為可能。但我還是決定不用它,因?yàn)槲矣X(jué)得(這個(gè) gem)讓 Go 程序作為服務(wù)端在后臺(tái)運(yùn)行,然后通過(guò) Unix 域套接字來(lái)與前端的 Ruby 程序通信有點(diǎn)太麻煩了,***我嘗試了一個(gè)直截了當(dāng)?shù)姆椒?
其實(shí)非常簡(jiǎn)單: 讓 Go 程序返回一個(gè) JSON 格式的數(shù)據(jù),然后在 Ruby 程序里解析它。 這樣一來(lái),我們就能用 Go 程序加速所有資源密集型任務(wù)了。他們將會(huì)在服務(wù)器上被編譯進(jìn)二進(jìn)制文件。這些 Go 程序在每次被調(diào)用之后都會(huì)返回一個(gè) JSON 格式的數(shù)據(jù)給 Ruby 程序使用。
1. Go 方面
我們期望Go程序能返回一個(gè)JSON,用Ruby解析標(biāo)準(zhǔn)化輸出,這有個(gè)例子。
雖然有很多復(fù)雜的好用的程序用的是自有變量,但是中心思想不會(huì)變了。
2. Ruby 方面
Ruby 代碼則可精簡(jiǎn)到一行 :
為了保持井井有條,Go程序會(huì)被放在自己的文件夾里。這樣部署起來(lái)容易點(diǎn)。然后寫(xiě)一個(gè)執(zhí)行對(duì)應(yīng)的Go程序的類(lèi),來(lái)解析和響應(yīng)JSON。在生產(chǎn)環(huán)境中則會(huì)用二進(jìn)制包來(lái)增加執(zhí)行效率。下面是一則類(lèi)的可能:
用method_missing這個(gè)類(lèi),在不改變Ruby代碼的情況下,讓新的Go程序跑起來(lái)。開(kāi)發(fā)者只需按照這個(gè)規(guī)則,添加新程序就可以了。
怎么組織代碼?
筆者贊成直接把Go代碼包含到你的主資源庫(kù)內(nèi)。如果要添加的程序的大小和范圍所剩無(wú)幾,你可以使用源控制來(lái)多獲取一些。主要是Ruby程序和Go程序之間的版本要不一致。例子中,我把代碼保存到: my_app/go/program1/
部署
用Go構(gòu)建程序,Go生成的二進(jìn)制包既可以在本地環(huán)境運(yùn)行,也可以在產(chǎn)品上運(yùn)行。唯一的問(wèn)題是怎樣部署這些文件:即可以上傳到云存儲(chǔ)上(如Amazon S3),然后在部署環(huán)境上依次下載,也可以直接上傳到部署環(huán)境。在我們的例子中,我們添加定制任務(wù)到 Capistrano (戳這里看腳本 用的是上傳到S3的方法) :
結(jié)論
學(xué)習(xí)Go可能會(huì)帶給你在當(dāng)前Ruby中解決問(wèn)題的思路,而不會(huì)帶來(lái)另外的設(shè)置上的麻煩。我特別推薦看一下那些比較好的Go例程和專(zhuān)欄。
英文原文:Using Go to improve your Ruby application's performance