您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關(guān)Go語言中怎么實(shí)現(xiàn)每分鐘處理100萬個(gè)請求,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
Go語言程序的單純方法
最初我們采取了一個(gè)非常單純的POST處理方式,僅僅試圖將任務(wù)并行化處理放到一個(gè)簡單的goroutine:
對于中等負(fù)載來說,這可能對大多數(shù)人是有效的,但這很快證明在大型負(fù)載時(shí),效果不太好。我們預(yù)期有很多的請求,但當(dāng)我們部署第一個(gè)版本到產(chǎn)品中時(shí),并沒有看到這個(gè)數(shù)量級的請求。我們完全低估了流量。
上面的方法在幾個(gè)方面都不好,沒有辦法控制我們正在大量生產(chǎn)的Go程序要產(chǎn)生多少個(gè)例程。由于我們每分鐘收到100萬個(gè)POST請求,理所當(dāng)然的,這段代碼很快就崩潰了。
再次嘗試
我們需要尋找一個(gè)不同的方式。從一開始,我們就討論如何保持請求處理程序的生命周期非常短,并在后臺生成處理進(jìn)程。當(dāng)然,這是必須在Ruby on Rails領(lǐng)域要做的,否則這將限制所有可用的web處理器,無論你使用的是puma, unicorn, passenger中的哪一個(gè)(請不要參加JRuby討論)。那么我們就需要利用通用的解決方案去做這個(gè),例如Resque, Sidekiq, SQS,等等。清單還可以繼續(xù)列下去,因?yàn)橛泻芏喾椒梢宰龅竭@一點(diǎn)。
所以第二個(gè)版本是創(chuàng)建一個(gè)緩存通道,在這里我們可以對一些作業(yè)進(jìn)行排隊(duì)并上傳到S3,由于我們可以控制隊(duì)列中的最大項(xiàng)目數(shù),在內(nèi)存中我們有足夠多的RAM對任務(wù)進(jìn)行排隊(duì),我們認(rèn)為只在通道隊(duì)列中緩存作業(yè)是可以的。
然后實(shí)際上的作業(yè)出列和處理,我們使用的是類似的函數(shù):
說實(shí)話,我不知道我們在想什么。這一定是一個(gè)充滿紅牛的深夜。這種方法沒有給我們帶來任何好處,我們用緩沖隊(duì)列來交換有缺陷的并發(fā),也只是推遲了問題的產(chǎn)生時(shí)間而已。我們的同步處理器一次只上傳一個(gè)有效負(fù)載到S3,而且由于傳入請求的速率比單處理器上傳到S3的能力大得多,所以緩沖通道很快就達(dá)到了極限,限制了請求處理程序來排隊(duì)更多項(xiàng)目的能力。
我們只是簡單地回避這個(gè)問題,最終導(dǎo)致系統(tǒng)的死亡。在我們部署了這個(gè)有缺陷的版本之后,我們的延遲率以不變的速率持續(xù)增長。
更好的解決方案
當(dāng)使用Go語言通道時(shí),我們決定利用通用模式以便創(chuàng)造一個(gè)2階的通道系統(tǒng),一個(gè)用于作業(yè)排隊(duì),另外一個(gè)控制多少作業(yè)者同時(shí)在JobQueue上操作。
這個(gè)想法是以某種可持續(xù)的速度并行上傳到S3,它既不會削弱機(jī)器性能,也不會從S3開始生成連接錯(cuò)誤。所以我們選擇了創(chuàng)建一個(gè)作業(yè)/作業(yè)者模式。對那些熟悉java,C#等語言的人來說,可以考慮采用Go語言實(shí)現(xiàn)通道方式而不是作業(yè)者線程池的方式。
我們修改了Web請求處理程序,創(chuàng)建一個(gè)帶負(fù)載的jobstruct實(shí)例,發(fā)送到JobQueue通道,便于作業(yè)者去拾取。
在網(wǎng)站服務(wù)器初始化過程中,我們創(chuàng)建一個(gè)Dispatcher,調(diào)用Run()去創(chuàng)建一個(gè)作業(yè)者池,開始偵聽出現(xiàn)在JobQueue的作業(yè)。
dispatcher := NewDispatcher(MaxWorker)
dispatcher.Run()
下面是用于dispatcher執(zhí)行的代碼:
注意,我們會提供被實(shí)例化和被添加到作業(yè)者池的最大的作業(yè)者量。 因?yàn)槲覀冞@個(gè)帶有dockerized Go環(huán)境的項(xiàng)目使用了亞馬遜Elasticbeanstalk,我們總是設(shè)法遵循12要素方法論來配置生產(chǎn)中的系統(tǒng),從環(huán)境變量中讀取這些數(shù)值。這樣就可以控制有多少作業(yè)者和作業(yè)隊(duì)列的最大值,因此,我們可以快速地調(diào)整這些值,而不需要重新部署集群。
var (
MaxWorker = os.Getenv(“MAX_WORKERS”)
MaxQueue = os.Getenv(“MAX_QUEUE”)
)
在部署完它之后,我們立刻發(fā)現(xiàn)所有的延遲率都降到了無關(guān)緊要的數(shù)字,系統(tǒng)處理請求的能力急劇上升。
彈性負(fù)載均衡完全預(yù)熱幾分鐘后,我們看到ElasticBeanstalk應(yīng)用服務(wù)每分鐘逼近100萬個(gè)請求。通常在早晨的幾個(gè)小時(shí)里,流量高峰會超過每分鐘100萬個(gè)請求。
一旦我們部署了新的代碼,服務(wù)器的數(shù)量從100臺減少到大約20臺。
在恰當(dāng)?shù)嘏渲昧思汉妥詣涌s放設(shè)置以后,我們能夠把它降低到僅有4x EC2 c4。如果CPU連續(xù)5分鐘超過90%,大型實(shí)例和彈性自動縮放設(shè)置就生成一個(gè)新實(shí)例。
看完上述內(nèi)容,你們對Go語言中怎么實(shí)現(xiàn)每分鐘處理100萬個(gè)請求有進(jìn)一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。