1. 程式人生 > >【Golang】百萬級高併發實踐

【Golang】百萬級高併發實踐

轉自:https://blog.csdn.net/jeanphorn/article/details/79018205

寫在前面

Go語言作為新興的語言,最近發展勢頭很是迅猛,其最大的特點就是原生支援併發。它使用的是“協程(goroutine)模型”,和傳統基於 OS 執行緒和程序實現不同,Go 
語言的併發是基於使用者態的併發,這種併發方式就變得非常輕量,能夠輕鬆執行幾萬併發邏輯。

Go 的併發屬於 CSP 併發模型的一種實現,CSP 併發模型的核心概念是:“不要通過共享記憶體來通訊,而應該通 
過通訊來共享記憶體”。這在 Go 語言中的實現就是 Goroutine 和 Channel。

場景描述

在一些場景下,有大規模請求(十萬或百萬級qps),我們處理的請求可能不需要立馬知道結果,例如資料的打點,檔案的上傳等等。這時候我們需要非同步化處理。常用的方法有使用resque、MQ、RabbitMQ等。這裡我們在Golang語言裡進行設計實踐。

方案演進

  1. 直接使用goroutine

在Go語言原生併發的支援下,我們可以直接使用一個goroutine(如下方式)去並行處理這個請求。但是,這種方法明顯有些不好的地方,我們沒法控制goroutine產生數量,如果處理程式稍微耗時,在單機萬級十萬級qps請求下,goroutine大規模爆發,記憶體暴漲,處理效率會很快下降甚至引發程式崩潰。

...
go handle(request)
...
  • 1
  • 2
  • 3
  • 4
  1. 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

講真,這種方法使用了緩衝佇列一定程度上了提高了併發,但也是治標不治本,大規模併發只是推遲了問題的發生時間。當請求速度遠大於佇列的處理速度時,緩衝區很快被打滿,後面的請求一樣被堵塞了。

  1. 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

BZOJ3143HNOI2013遊走 斯消元

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 直接 當你從客戶端接收到一串序列化後的數據,你需要   - 修改其中某一個標簽的值,然後把它傳遞到真正的業務數據,這樣每個業務模塊(微服務)就不需要和公共授權服務打交道了。   - 因為傳

JavaJ.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

SpringCloud04——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.大資