自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何用Go語言每分鐘處理100萬個(gè)請求

開發(fā) 后端
作者結(jié)合自身工作經(jīng)歷,以一個(gè)項(xiàng)目為案例,通過多個(gè)Go語言程序?qū)嵗膰L試,闡述了Go語言是如何每分鐘可以處理100萬個(gè)請求的。

摘要:作者結(jié)合自身工作經(jīng)歷,以一個(gè)項(xiàng)目為案例,通過多個(gè)Go語言程序?qū)嵗膰L試,闡述了Go語言是如何每分鐘可以處理100萬個(gè)請求的,以下是譯文。

我在幾個(gè)不同的公司從事反垃圾郵件,反病毒和反惡意軟件工作超過15年,現(xiàn)在我知道這些系統(tǒng)的復(fù)雜性可能是由于我們每天處理的大量數(shù)據(jù)造成的。

目前,我是 smsjunk.com 的CEO和 KnowBe4 的***架構(gòu)師,兩個(gè)活躍在網(wǎng)絡(luò)安全行業(yè)的公司。

有趣的是,在過去10年左右的時(shí)間里,作為一名軟件工程師,我所參與的所有web后端開發(fā)大部分都是以Ruby on Rails(Rails是使用Ruby語言編寫的網(wǎng)頁程序開發(fā)框架,目的是為開發(fā)者提供常用組件)開發(fā)的。不要誤會(huì)我,我熱愛Ruby on Rails,我相信它是一個(gè)令人著迷的開發(fā)環(huán)境,但一段時(shí)間后,你開始以Ruby的方式思考和設(shè)計(jì)系統(tǒng),忘了如何高效和原本可以利用多線程、并行、快速執(zhí)行和小的內(nèi)存消耗來簡化軟件架構(gòu)。多年來,我是一個(gè)C / C++、Delphi和C #開發(fā)人員,我剛剛意識(shí)到,用合適的工具來完成工作可能會(huì)降低事情的復(fù)雜度。

我不太熱衷于開發(fā)語言和框架的戰(zhàn)爭,網(wǎng)站之間總是為此爭吵。我相信效率、生產(chǎn)率和代碼的可維護(hù)性主要取決于如何簡單地構(gòu)建解決方案。 問題

當(dāng)我們在一個(gè)匿名的遙測和分析系統(tǒng)上工作時(shí),我們的目標(biāo)是能夠處理來自數(shù)百萬終端的大量的POST請求。Web處理程序?qū)⒔邮找粋€(gè)JSON文檔,其中可能包含需要寫入Amazon S3的許多有效負(fù)載的集合,這是為了使map-reduce系統(tǒng)稍后操作這個(gè)數(shù)據(jù)。

傳統(tǒng)上,我們將研究創(chuàng)造一個(gè)一階作業(yè)者架構(gòu),利用諸如:

  • Sidekiq
  • Resque
  • DelayedJob
  • Elasticbeanstalk Worker Tier
  • RabbitMQ
  • 等等…

設(shè)置2個(gè)不同的集群,一個(gè)用于web前端,另一個(gè)用于作業(yè)者,這樣會(huì)擴(kuò)大可以處理的后臺(tái)工作的數(shù)量。

但從一開始,我們的團(tuán)隊(duì)就知道應(yīng)該這樣做,因?yàn)樵谟懻撾A段,我們預(yù)見這可能是一個(gè)非常大的流量系統(tǒng)。我使用Go語言大約2年左右的時(shí)間,我們開發(fā)了一些在用的系統(tǒng),但是沒有一個(gè)系統(tǒng)能得到這么多的負(fù)載。

首先通過創(chuàng)建一些structure,定義通過POST調(diào)用來接收到的web請求負(fù)載,還有一個(gè)上傳請求負(fù)載到S3 bucket的函數(shù)。

如何用Go語言每分鐘處理100萬個(gè)請求

Go語言程序的單純方法

最初我們采取了一個(gè)非常單純的POST處理方式,僅僅試圖將任務(wù)并行化處理放到一個(gè)簡單的goroutine:

如何用Go語言每分鐘處理100萬個(gè)請求

對于中等負(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è)不同的方式。從一開始,我們就討論如何保持請求處理程序的生命周期非常短,并在后臺(tái)生成處理進(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è)是可以的。

如何用Go語言每分鐘處理100萬個(gè)請求

然后實(shí)際上的作業(yè)出列和處理,我們使用的是類似的函數(shù):

如何用Go語言每分鐘處理100萬個(gè)請求

說實(shí)話,我不知道我們在想什么。這一定是一個(gè)充滿紅牛的深夜。這種方法沒有給我們帶來任何好處,我們用緩沖隊(duì)列來交換有缺陷的并發(fā),也只是推遲了問題的產(chǎn)生時(shí)間而已。我們的同步處理器一次只上傳一個(gè)有效負(fù)載到S3,而且由于傳入請求的速率比單處理器上傳到S3的能力大得多,所以緩沖通道很快就達(dá)到了極限,限制了請求處理程序來排隊(duì)更多項(xiàng)目的能力。

我們只是簡單地回避這個(gè)問題,最終導(dǎo)致系統(tǒng)的死亡。在我們部署了這個(gè)有缺陷的版本之后,我們的延遲率以不變的速率持續(xù)增長。

如何用Go語言每分鐘處理100萬個(gè)請求

更好的解決方案

當(dāng)使用Go語言通道時(shí),我們決定利用通用模式以便創(chuàng)造一個(gè)2階的通道系統(tǒng),一個(gè)用于作業(yè)排隊(duì),另外一個(gè)控制多少作業(yè)者同時(shí)在JobQueue上操作。

這個(gè)想法是以某種可持續(xù)的速度并行上傳到S3,它既不會(huì)削弱機(jī)器性能,也不會(huì)從S3開始生成連接錯(cuò)誤。所以我們選擇了創(chuàng)建一個(gè)作業(yè)/作業(yè)者模式。對那些熟悉java,C#等語言的人來說,可以考慮采用Go語言實(shí)現(xiàn)通道方式而不是作業(yè)者線程池的方式。

如何用Go語言每分鐘處理100萬個(gè)請求如何用Go語言每分鐘處理100萬個(gè)請求如何用Go語言每分鐘處理100萬個(gè)請求

我們修改了Web請求處理程序,創(chuàng)建一個(gè)帶負(fù)載的jobstruct實(shí)例,發(fā)送到JobQueue通道,便于作業(yè)者去拾取。

如何用Go語言每分鐘處理100萬個(gè)請求

在網(wǎng)站服務(wù)器初始化過程中,我們創(chuàng)建一個(gè)Dispatcher,調(diào)用Run()去創(chuàng)建一個(gè)作業(yè)者池,開始偵聽出現(xiàn)在JobQueue的作業(yè)。

 

  1. dispatcher := NewDispatcher(MaxWorker)  
  2. dispatcher.Run() 

下面是用于dispatcher執(zhí)行的代碼:

如何用Go語言每分鐘處理100萬個(gè)請求如何用Go語言每分鐘處理100萬個(gè)請求

注意,我們會(huì)提供被實(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)整這些值,而不需要重新部署集群。

 

  1. var (  
  2. MaxWorker = os.Getenv(“MAX_WORKERS”)  
  3. MaxQueue = os.Getenv(“MAX_QUEUE”)  

在部署完它之后,我們立刻發(fā)現(xiàn)所有的延遲率都降到了無關(guān)緊要的數(shù)字,系統(tǒng)處理請求的能力急劇上升。

如何用Go語言每分鐘處理100萬個(gè)請求

彈性負(fù)載均衡完全預(yù)熱幾分鐘后,我們看到ElasticBeanstalk應(yīng)用服務(wù)每分鐘逼近100萬個(gè)請求。通常在早晨的幾個(gè)小時(shí)里,流量高峰會(huì)超過每分鐘100萬個(gè)請求。

一旦我們部署了新的代碼,服務(wù)器的數(shù)量從100臺(tái)減少到大約20臺(tái)。

如何用Go語言每分鐘處理100萬個(gè)請求

在恰當(dāng)?shù)嘏渲昧思汉妥詣?dòng)縮放設(shè)置以后,我們能夠把它降低到僅有4x EC2 c4。如果CPU連續(xù)5分鐘超過90%,大型實(shí)例和彈性自動(dòng)縮放設(shè)置就生成一個(gè)新實(shí)例。

如何用Go語言每分鐘處理100萬個(gè)請求

結(jié)論

簡單總是在我的字典里獲勝。我們可以設(shè)計(jì)一個(gè)復(fù)雜系統(tǒng),它具有多隊(duì)列,后臺(tái)作業(yè)者,復(fù)雜部署的特點(diǎn)。但是相反我們決定利用Elasticbeanstalk的自動(dòng)縮放和高效簡單的方式去并發(fā),Go語言很好的提供了這些功能。

并不是每天你僅有四臺(tái)機(jī)器的集群,去處理每分鐘寫入到亞馬遜S3 bucket的100萬個(gè)POST請求,這可能比我***的MacBook Pro功能強(qiáng)大的多。

總有合適的工具適合這項(xiàng)工作。有時(shí),當(dāng)您的Ruby on Rails系統(tǒng)需要一個(gè)非常強(qiáng)大的web處理程序時(shí),可以稍微考慮一下Ruby生態(tài)系統(tǒng)之外的更簡單、更強(qiáng)大的替代解決方案。

責(zé)任編輯:未麗燕 來源: ITeye
相關(guān)推薦

2019-07-02 14:05:23

Go語言高并發(fā)

2023-10-31 07:52:10

2021-07-27 06:05:07

網(wǎng)絡(luò)犯罪網(wǎng)絡(luò)攻擊網(wǎng)絡(luò)威脅

2013-08-19 11:27:24

谷歌宕機(jī)損失

2022-10-08 00:05:00

HammerDB自動(dòng)化測試

2011-09-05 10:07:49

聯(lián)想激光打印機(jī)

2025-03-13 08:33:37

RPMTPM代碼

2011-09-06 08:42:58

惠普激光打印機(jī)

2011-09-19 13:27:36

惠普激光打印機(jī)

2011-11-23 13:54:21

惠普激光打印機(jī)

2012-02-23 14:10:16

惠普激光打印機(jī)

2012-01-09 15:14:41

惠普激光打印機(jī)

2012-05-24 11:38:00

惠普激光打印機(jī)

2012-08-07 14:33:49

打印機(jī)

2012-08-01 10:18:47

打印機(jī)

2012-04-20 14:42:45

夏普復(fù)合一體機(jī)

2010-08-26 17:39:48

谷歌

2012-06-04 11:18:02

HP激光打印機(jī)

2021-08-26 06:58:14

Http請求url

2011-11-25 13:39:55

聯(lián)想激光打印機(jī)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)