【Golang】百萬級高併發實踐
轉自:https://blog.csdn.net/jeanphorn/article/details/79018205
寫在前面
Go語言作為新興的語言,最近發展勢頭很是迅猛,其最大的特點就是原生支援併發。它使用的是“協程(goroutine)模型”,和傳統基於 OS 執行緒和程序實現不同,Go
語言的併發是基於使用者態的併發,這種併發方式就變得非常輕量,能夠輕鬆執行幾萬併發邏輯。
Go 的併發屬於 CSP 併發模型的一種實現,CSP 併發模型的核心概念是:“不要通過共享記憶體來通訊,而應該通
過通訊來共享記憶體”。這在 Go 語言中的實現就是 Goroutine 和 Channel。
場景描述
在一些場景下,有大規模請求(十萬或百萬級qps),我們處理的請求可能不需要立馬知道結果,例如資料的打點,檔案的上傳等等。這時候我們需要非同步化處理。常用的方法有使用resque、MQ、RabbitMQ等。這裡我們在Golang語言裡進行設計實踐。
方案演進
- 直接使用goroutine
在Go語言原生併發的支援下,我們可以直接使用一個goroutine(如下方式)去並行處理這個請求。但是,這種方法明顯有些不好的地方,我們沒法控制goroutine產生數量,如果處理程式稍微耗時,在單機萬級十萬級qps請求下,goroutine大規模爆發,記憶體暴漲,處理效率會很快下降甚至引發程式崩潰。
...
go handle(request)
...
- 1
- 2
- 3
- 4
goroutine協同帶快取的管道
- 我們定義一個帶快取的管道;
var queue = make(chan job, MAX_QUEUE_SIZE)
- 1
- 然後起一個協程處理管道傳來的請求;
go func(){
for {
select {
case job := <-queue:
job.Do(request)
case <- quit:
return
}
}
}()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 接收請求,傳送job進行處理
job := &Job{request}
queue <- job
- 1
- 2
- 3
講真,這種方法使用了緩衝佇列一定程度上了提高了併發,但也是治標不治本,大規模併發只是推遲了問題的發生時間。當請求速度遠大於佇列的處理速度時,緩衝區很快被打滿,後面的請求一樣被堵塞了。
- job佇列+工作池
只用緩衝佇列不能解決根本問題,這時候我們可以參考一下執行緒池的概念,定一個工作池(協程池),來限定最大goroutine數目。每次來新的job時,從工作池裡取出一個可用的worker來執行job。這樣一來即保障了goroutine的可控性,也儘可能大的提高了併發處理能力。
工作池實現
- 首先,我們定義一個job的介面, 具體內容由具體job實現;
type Job interface {
Do() error
}
- 1
- 2
- 3
- 然後定義一下job佇列和work池型別,這裡我們work池也用golang的channel實現。
// define job channel
type JobChan chan Job
// define worker channer
type WorkerChan chan JobChan
- 1
- 2
- 3
- 4
- 5
- 6
我們分別維護一個全域性的job佇列和工作池。
var (
JobQueue JobChan
WorkerPool WorkerChan
)
- 1
- 2
- 3
- 4
- 5
- worker的實現。每一個worker都有一個job channel,在啟動worker的時候會被註冊到work pool中。啟動後通過自身的job channel取到job並執行job。
type Worker struct {
JobChannel JobChan
quit chan bool
}
func (w *Worker) Start() {
go func() {
for {
// regist current job channel to worker pool
WorkerPool <- w.JobChannel
select {
case job := <-w.JobChannel:
if err := job.Do(); err != nil {
fmt.printf("excute job failed with err: %v", err)
}
// recieve quit event, stop worker
case <-w.quit:
return
}
}
}()
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 實現一個分發器(Dispatcher)。分發器包含一個worker的指標陣列,啟動時例項化並啟動最大數目的worker,然後從job佇列中不斷取job選擇可用的worker來執行job。
type Dispatcher struct {
Workers []*Worker
quit chan bool
}
func (d *Dispatcher) Run() {
for i := 0; i < MaxWorkerPoolSize; i++ {
worker := NewWorker()
d.Workers = append(d.Workers, worker)
worker.Start()
}
for {
select {
case job := <-JobQueue:
go func(job Job) {
jobChan := <-WorkerPool
jobChan <- job
}(job)
// stop dispatcher
case <-d.quit:
return
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
感謝
相關推薦
【Golang】百萬級高併發實踐
轉自:https://blog.csdn.net/jeanphorn/article/details/79018205寫在前面Go語言作為新興的語言,最近發展勢頭很是迅猛,其最大的特點就是原生支援併發。它使用的是“協程(goroutine)模型”,和傳統基於 OS 執行緒和程
Golang百萬級高併發實踐
寫在前面 Go語言作為新興的語言,最近發展勢頭很是迅猛,其最大的特點就是原生支援併發。它使用的是“協程(goroutine)模型”,和傳統基於 OS 執行緒和程序實現不同,Go 語言的併發是基於使用者態的併發,這種併發方式就變得非常輕量,能夠輕鬆執行幾萬併發邏輯。 Go 的併發屬於
**epoll實現tcp百萬級高併發測試**
**epoll實現高併發測試** 1,準備環境 Server 端: 系統埠限制 預設檢視:cat /proc/sys/net/ipv4/ip_local_port_range 32768 60999(在/etc/sysctl.conf修改) 最大檔案控制代碼限制:檢
MySQL百萬級高併發網站實戰攻略
本人小菜鳥一隻,為了自我學習和交流PHP(jquery,linux,lamp,shell,javascript,伺服器)等一系列的知識,小菜鳥建立了一個群。希望光臨本部落格的人可以進來交流。尋求共同
【轉】聊聊java高併發系統之非同步非阻塞
在做電商系統時,流量入口如首頁、活動頁、商品詳情頁等系統承載了網站的大部分流量,而這些系統的主要職責包括聚合資料拼裝模板、熱點統計、快取、下游功能降級開關、託底資料等等。其中聚合資料需要呼叫其它多個系統服務獲取資料、拼裝資料/模板然後返回給前端,聚合資料來源主要有依賴系統/服務、快取、資料庫等;而系統之間
Golang百萬級高並發實例
minute 一個 ase 效果 tin n) 無限 chan 會有 前言 感謝Handling 1 Million Requests per Minute with Go 這篇文章給予的巨大啟發。 基礎 我們使用Go語言,基本上是因為他原生支持的高並發:Goroutine
【備忘】Java高效能高併發秒殺系統實戰視訊教程
1-1 java高併發商城秒殺優化導學.mp41-2 專案環境搭建(Eclipse).mp41-3 專案環境搭建(IDEA).mp41-4 整合mybatis.mp41-5 安裝redis.mp41-6 整合redis上.mp41-7 整合redis中.mp41-8 整合r
【搶購/秒殺】redis實現高併發下的搶購/秒殺功能
開發十年,就只剩下這套架構體系了! >>>
【秒殺搶購】關於php高併發解決的一點思路
開發十年,就只剩下這套架構體系了! >>>
【MyBatis】-----【MyBatis】---表級聯系【一對多】
new pda 聯合 測試 asr exc ack 負責 trace 一、核心配置文件 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//myba
【BZOJ3143】【HNOI2013】遊走 高斯消元
pri OS 發現 scan span 高斯 hnoi2013 c代碼 main 題目傳送門:http://www.lydsy.com/JudgeOnline/problem.php?id=3143 我們令$P_i$表示從第i號點出發的期望次數。則$P_n$顯然為$0$。
MySQL基礎入門學習【9】無限級分類表設計
父親 連接 參照物 insert gpo 平板電視 生活電器 type mysql 比如: 圖書/小說、文學.../四大名著、戲曲.../... 理論上可以設計很多張表; 但是隨著分類逐步增多,這些表的數目不可能無限擴展; 所以對於無限級分類表一般我們采用如下形式(通過自身
【Golang】讀源碼知 【encode/binary】
傳遞 規則 AR 不能 反序列化 lan light str window go version go1.9.2 windows/amd64 如果你覺得xml,json等不能滿足你程序的需要,那麽你可能用到傳統的二進制協議來作為服務之間數據協議 1. 頂層結構可以
【Golang】如何不反序列化為前提的情況下,修改ProtoBuffer某個Tag的值
刪除 tag mage msg 挑戰 客戶 Golan protobuff 直接 當你從客戶端接收到一串序列化後的數據,你需要 - 修改其中某一個標簽的值,然後把它傳遞到真正的業務數據,這樣每個業務模塊(微服務)就不需要和公共授權服務打交道了。 - 因為傳
【Java】J.U.C併發包 - AQS機制
簡介 Java併發包(java.util.concurrent)中提供了很多併發工具,這其中,很多我們耳熟能詳的併發工具,譬如ReentrantLock、Semaphore,CountDownLatch,CyclicBarrier,它們的實現都用到了一個共同的基類 - Abstrac
【演算法】第三章作業 實踐報告
【演算法】實踐第三章作業 1. 實踐題目 最大子段和 2. 問題描述 給定n個整數(可能為負數)組成的序列a[1],a[2],a[3],…,a[n],求該序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。當所給的整數均為負數時,定義子段和為0。
Netty 100萬級高併發伺服器配置
前言 每一種該語言在某些極限情況下的表現一般都不太一樣,那麼我常用的Java語言,在達到100萬個併發連線情況下,會怎麼樣呢,有些好奇,更有些期盼。 這次使用經常使用的順手的netty NIO框架(netty-3.6.5.Final),封裝的很好,介面很全面,就像它現在的域名 netty.io,專注於網路I
【SpringCloud】04——Eureka高可用叢集
1.為什麼需要Eureka叢集? Eureka作為服務註冊中心,讓服務作為客戶端註冊進來,但是假如Eureka壞了的話,所有的服務都將不能進行互相呼叫,為了高可用,所以需要搭建Eureka叢集來解決該問題。 2.搭建叢集我們需要做的幾步工作: 2.1.新增工程,配置pom ,yml
【MYSQL】比前一天高的溫度
給定一個 Weather 表,編寫一個 SQL 查詢,來查詢與之前(昨天的)日期相比溫度更高的所有日期的 Id。 例如,根據上述給定的 Weather 表格,返回如下 Id: 解法一:使用to_days()。TO_DAYS(date)
JAVA架構師大型分散式高併發電商專案實戰,效能優化,叢集,億級高併發,web安全,快取架構實戰
現任58到家技術委員會主席,高階技術總監,負責企業,支付,營銷、客戶關係等多個後端業務部門。本質,技術人一枚。網際網路架構技術專家,“架構師之路”公眾號作者。曾任百度高階工程師,58同城高階架構師,58同城技術委員會主席,58同城C2C技術部負責人。 內容介紹 1.大資