1. 程式人生 > >如何用Go語言每分鐘處理100萬個請求

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

摘要:作者結合自身工作經歷,以一個專案為案例,通過多個Go語言程式例項的嘗試,闡述了Go語言是如何每分鐘可以處理100萬個請求的,以下是譯文。

我在幾個不同的公司從事反垃圾郵件,反病毒和反惡意軟體工作超過15年,現在我知道這些系統的複雜性可能是由於我們每天處理的大量資料造成的。

目前,我是smsjunk.com的CEO和KnowBe4的首席架構師,兩個活躍在網路安全行業的公司。

有趣的是,在過去10年左右的時間裡,作為一名軟體工程師,我所參與的所有web後端開發大部分都是以Ruby on Rails(Rails是使用Ruby語言編寫的網頁程式開發框架,目的是為開發者提供常用元件)開發的。不要誤會我,我熱愛Ruby on Rails,我相信它是一個令人著迷的開發環境,但一段時間後,你開始以Ruby的方式思考和設計系統,忘了如何高效和原本可以利用多執行緒、並行、快速執行和小的記憶體消耗來簡化軟體架構。多年來,我是一個C / C++、Delphi和C #開發人員,我剛剛意識到,用合適的工具來完成工作可能會降低事情的複雜度。

我不太熱衷於開發語言和框架的戰爭,網站之間總是為此爭吵。我相信效率、生產率和程式碼的可維護性主要取決於如何簡單地構建解決方案。

問題

當我們在一個匿名的遙測和分析系統上工作時,我們的目標是能夠處理來自數百萬終端的大量的POST請求。Web處理程式將接收一個JSON文件,其中可能包含需要寫入Amazon S3的許多有效負載的集合,這是為了使map-reduce系統稍後操作這個資料。

傳統上,我們將研究創造一個一階作業者架構,利用諸如:

  • Sidekiq

  • Resque

  • DelayedJob

  • Elasticbeanstalk Worker Tier

  • RabbitMQ

  • 等等…

設定2個不同的叢集,一個用於web前端,另一個用於作業者,這樣會擴大可以處理的後臺工作的數量。

但從一開始,我們的團隊就知道應該這樣做,因為在討論階段,我們預見這可能是一個非常大的流量系統。我使用Go語言大約2年左右的時間,我們開發了一些在用的系統,但是沒有一個系統能得到這麼多的負載。

首先通過建立一些structure,定義通過POST呼叫來接收到的web請求負載,還有一個上傳請求負載到S3 bucket的函式。

這裡寫圖片描述

Go語言程式的單純方法

最初我們採取了一個非常單純的POST處理方式,僅僅試圖將任務並行化處理放到一個簡單的goroutine:

這裡寫圖片描述

對於中等負載來說,這可能對大多數人是有效的,但這很快證明在大型負載時,效果不太好。我們預期有很多的請求,但當我們部署第一個版本到產品中時,並沒有看到這個數量級的請求。我們完全低估了流量。

上面的方法在幾個方面都不好,沒有辦法控制我們正在大量生產的Go程式要產生多少個例程。由於我們每分鐘收到100萬個POST請求,理所當然的,這段程式碼很快就崩潰了。

再次嘗試

我們需要尋找一個不同的方式。從一開始,我們就討論如何保持請求處理程式的生命週期非常短,並在後臺生成處理程序。當然,這是必須在Ruby on Rails領域要做的,否則這將限制所有可用的web處理器,無論你使用的是puma, unicorn, passenger中的哪一個(請不要參加JRuby討論)。那麼我們就需要利用通用的解決方案去做這個,例如Resque, Sidekiq, SQS,等等。清單還可以繼續列下去,因為有很多方法可以做到這一點。

所以第二個版本是建立一個快取通道,在這裡我們可以對一些作業進行排隊並上傳到S3,由於我們可以控制佇列中的最大專案數,在記憶體中我們有足夠多的RAM對任務進行排隊,我們認為只在通道佇列中快取作業是可以的。
這裡寫圖片描述

然後實際上的作業出列和處理,我們使用的是類似的函式:

這裡寫圖片描述

說實話,我不知道我們在想什麼。這一定是一個充滿紅牛的深夜。這種方法沒有給我們帶來任何好處,我們用緩衝佇列來交換有缺陷的併發,也只是推遲了問題的產生時間而已。我們的同步處理器一次只上傳一個有效負載到S3,而且由於傳入請求的速率比單處理器上傳到S3的能力大得多,所以緩衝通道很快就達到了極限,限制了請求處理程式來排隊更多專案的能力。

我們只是簡單地迴避這個問題,最終導致系統的死亡。在我們部署了這個有缺陷的版本之後,我們的延遲率以不變的速率持續增長。
這裡寫圖片描述

更好的解決方案

當使用Go語言通道時,我們決定利用通用模式以便創造一個2階的通道系統,一個用於作業排隊,另外一個控制多少作業者同時在JobQueue上操作。

這個想法是以某種可持續的速度並行上傳到S3,它既不會削弱機器效能,也不會從S3開始生成連線錯誤。所以我們選擇了建立一個作業/作業者模式。對那些熟悉java,C#等語言的人來說,可以考慮採用Go語言實現通道方式而不是作業者執行緒池的方式。
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述

我們修改了Web請求處理程式,建立一個帶負載的jobstruct例項,傳送到JobQueue通道,便於作業者去拾取。

這裡寫圖片描述

在網站伺服器初始化過程中,我們建立一個Dispatcher,呼叫Run()去建立一個作業者池,開始偵聽出現在JobQueue的作業。
dispatcher := NewDispatcher(MaxWorker)
dispatcher.Run()

下面是用於dispatcher執行的程式碼:
這裡寫圖片描述
這裡寫圖片描述

注意,我們會提供被例項化和被新增到作業者池的最大的作業者量。 因為我們這個帶有dockerized Go環境的專案使用了亞馬遜Elasticbeanstalk,我們總是設法遵循12要素方法論來配置生產中的系統,從環境變數中讀取這些數值。這樣就可以控制有多少作業者和作業佇列的最大值,因此,我們可以快速地調整這些值,而不需要重新部署叢集。

var (

MaxWorker = os.Getenv(“MAX_WORKERS”)

MaxQueue = os.Getenv(“MAX_QUEUE”)

)

在部署完它之後,我們立刻發現所有的延遲率都降到了無關緊要的數字,系統處理請求的能力急劇上升。

這裡寫圖片描述

彈性負載均衡完全預熱幾分鐘後,我們看到ElasticBeanstalk應用服務每分鐘逼近100萬個請求。通常在早晨的幾個小時裡,流量高峰會超過每分鐘100萬個請求。

一旦我們部署了新的程式碼,伺服器的數量從100臺減少到大約20臺。

這裡寫圖片描述

在恰當地配置了叢集和自動縮放設定以後,我們能夠把它降低到僅有4x EC2 c4。如果CPU連續5分鐘超過90%,大型例項和彈性自動縮放設定就生成一個新例項。

這裡寫圖片描述

結論

簡單總是在我的字典裡獲勝。我們可以設計一個複雜系統,它具有多佇列,後臺作業者,複雜部署的特點。但是相反我們決定利用Elasticbeanstalk的自動縮放和高效簡單的方式去併發,Go語言很好的提供了這些功能。

並不是每天你僅有四臺機器的叢集,去處理每分鐘寫入到亞馬遜S3 bucket的100萬個POST請求,這可能比我最新的MacBook Pro功能強大的多。

總有合適的工具適合這項工作。有時,當您的Ruby on Rails系統需要一個非常強大的web處理程式時,可以稍微考慮一下Ruby生態系統之外的更簡單、更強大的替代解決方案。

相關推薦

如何用Go語言分鐘處理100請求

摘要:作者結合自身工作經歷,以一個專案為案例,通過多個Go語言程式例項的嘗試,闡述了Go語言是如何每分鐘可以處理100萬個請求的,以下是譯文。我在幾個不同的公司從事反垃圾郵件,反病毒和反惡意軟體工作超過15年,現在我知道這些系統的複雜性可能是由於我們每天處理的大

資深程序員Python實現處理 120 次 HTTP 請求!什麽概念

更多 PE aws wsgi 語言 對象 虛擬 釋放 功能 Python 的微框架(藍色)、NodeJS 和 Go (綠色) 和 Japronto (紫色) 勘誤表:用戶 @heppu 提到,如果謹慎點用 Go 的 stdlib HTTP 服

假設網絡的生產管理系統采B/S工作方式,經常上網的戶數為100,每個分鐘平均產生11事務,平均事務量大小為0.06MB,則這個系統需要的傳輸速率為(34)。

上半年 16px 產生 字節 需要 方式 解析 傳輸 nbsp 2014年上半年 網絡工程師 上午試卷 綜合知識 假設網絡的生產管理系統采用B/S工作方式,經常上網的用戶數為100個,每個用戶每分鐘平均產生11個事務,平均事務量大小為0.06MB,則這個系統需要的傳輸

c語言指針處理字符串

image tdi while clas int color result 處理 std 字符串的處理方法有兩種:一種方法是使用字符數組處理字符串,另一種是方法是使用字符指針處理字符串。 後一種也是c語言比較常用的方法。下面我們來看一個列子: 1 #include<

SQL統計分鐘的訪問量

沒有 -m count blog 意思 har div weight 面試 以前面試沒有理解到它什麽意思的一道題,回憶中是這個題意 select count(1), to_char(r.datelastmaint, ‘yyyy-mm-dd hh24:mi‘

處理10高並發訂單的樂視集團支付系統架構分享

記錄 應該 高校 操作 新的 讀寫 官方 來看 一個表 隨著樂視硬件搶購的不斷升級,樂視集團支付面臨的請求壓力百倍乃至千倍的暴增。作為商品購買的最後一環,保證用戶快速穩定的完成支付尤為重要。所以在15年11月,我們對整個支付系統進行了全面的架構升級,使之具備了每秒穩定處理1

Go語言中日誌處理,log包的使用

Go語言日誌 Go語言log golang日誌處理 Golang提供了原生日誌庫“log”,使用簡單方便,本文以代碼為例進行說明介紹。 package main import ( "os" "log" "fmt" ) func main() { // 打開日誌文

雙11同款!阿裏雲發布全局事務服務GTS:處理10筆事務

互聯網摘要: 5月30日,阿裏雲宣布全局事務服務產品GTS正式商用,每秒可處理10萬筆事務,將分布式事務這個“貴族技術”變為“平民技術 ”,可解決跨數據庫、消息、服務的分布式環境下的事務一致性問題,讓開發者無需考慮復雜的事務問題,加速微服務落地,效率比傳統的XA協議提升了10倍之多。5月30日,阿裏雲宣布全局

go語言求1到100之內的質數

clas package 合數 math 自然 import 兩個 一個 imp 素數指在一個大於1的自然數中,除了1和此整數自身外,沒法被其他自然數整除的數。換句話說,只有兩個正因數(1和自己)的自然數即為素數(也叫質數)。比1大但不是素數的數稱為合數。1和0既非素數也

go語言實現類似java8的Stream

4.4 代碼 歸納 Go語言 浮點 print jdk 是我 遞歸 JDK8 Stream 是一個支持泛型和函數式數據流,使用起來非常強大方便。最近在學習 go 語言我就用 go 模仿了一下類似的功能,由於 go 對泛型、函數式的支持比較有限,感覺泛型和函數式這一塊實現起來

Go語言的異常處理之errors,panic, recover

package errors func text import type project args normal error接口:源碼 Go語言引入了一個關於錯誤處理的標準模式,即error接口,它是Go語言內建的接口類型,該接口的定義如下: type error inte

go語言寫的快速排序

因為工作原因接觸了go語言,由於其特性,並行程式設計非常方便。而go語言特有的入門級的特性最主要的就包括了用go開協程,用channel進行同步。 用這些入門級特性寫了一個多執行緒版本的快速排序是一個非常好的練習。 package main import ( "fmt" "sync"

處理10高併發訂單的某集團支付系統架構分享

轉載自:最程式碼 官方 隨著樂視硬體搶購的不斷升級,樂視集團支付面臨的請求壓力百倍乃至千倍的暴增。作為商品購買的最後一環,保證使用者快速穩定的完成支付尤為重要。所以在15年11月,我們對整個支付系統進行了全面的架構升級,使之具備了每秒穩定處理10萬訂單的能力。為樂視生態各種形式的搶購秒殺活動提供

在windows下go語言寫跨卷批量移動小工具

時值我小病在家休養生息,喜歡跳廣場舞的外公來尋求我的幫助,他們跳廣場舞是將存有歌曲的U盤插到音響上面,而音響大部分都是隻能顯示歌曲的索引index,不能直接顯示歌曲名,所以為了方便他們會在U盤裡面對歌曲進行排序。由於音響是定址按順序播放,意思就是在U盤裡面的歌曲需要一首一首的按順序複製過去,而且當對U盤歌曲進

Go語言實現selpg指令

一、selpg指令簡介 selpg 是一個自定義命令列程式,全稱select page,即從源(標準輸入流或檔案)讀取指定頁數的內容到目的地(標準輸出流或給給印表機列印)。selpg 是以在 Linux 中建立命令的事實上的約定為模型建立的,這些約定包括: 獨立工作 在

處理10高併發訂單的樂視集團支付系統架構分享

隨著樂視硬體搶購的不斷升級,樂視集團支付面臨的請求壓力百倍乃至千倍的暴增。作為商品購買的最後一環,保證使用者快速穩定的完成支付尤為重要。所以在15年11月,我們對整個支付系統進行了全面的架構升級,使之具備了每秒穩定處理10萬訂單的能力。為樂視生態各種形式的搶購秒殺活動提供

處理10高併發訂單的樂視集團支付系統架構分享【轉】

轉自:https://www.cnblogs.com/hackxhao/p/5496254.html 隨著樂視硬體搶購的不斷升級,樂視集團支付面臨的請求壓力百倍乃至千倍的暴增。作為商品購買的最後一環,保證使用者快速穩定的完成支付尤為重要。所以在15年11月,我們對整個支付系統進行了全面的架構升級

Go 語言與 EOS.IO 互動的 API 庫

用 Go 語言與 EOS.IO 互動的 API 庫,該庫提供對資料架構(二進位制打包和JSON介面)的簡單訪問,以及對遠端或本地執行的EOS.IO RPC伺服器的API呼叫。 它提供錢包功能(KeyBag),或者可以通過 keosd 錢包簽署交易。 它還明白埠9876上的P2P協議。 截

2000行程式碼go語言實現的比特幣基本的相關模型功能

|版權宣告:本文為博主原創文章,未經博主允許不得轉載。部落格地址:https://blog.csdn.net/sgsgy5 前言:閒暇時期,參考了一些資料,用go簡單的實現了比特幣中的一些相關功能,實現完全大概2000行程式碼左右,現在剛利用閒暇時間寫了一點小

我為什麼GO語言來做區塊鏈?

Go語言現在常常被用來做去中心化系統(decentralised system)。其他型別的公司也都把Go用在產品的核心模組中,並且它在網站開發中也佔據了一席之地。 我們在決定做Karachain的時候,考量(benchmark)了C,C++, Java, 甚