1. 程式人生 > >Go 自帶的 http/server.go 的連線解析 與 如何結合 master-worker 併發模式,提高單機併發能力

Go 自帶的 http/server.go 的連線解析 與 如何結合 master-worker 併發模式,提高單機併發能力

作者:林冠巨集 / 指尖下的幽靈

關於 server.go 原始碼的解析可以去搜下,已經有很多且還不錯的文章。

正文:

從我們啟動http.ListenAndServe(port,router)開始,server.go 內部最終在一個for 迴圈中的 accept 方法中不停地等待客戶端的連線到來。

每接收到一個accept 就啟動一個 gorutine 去處理當前ip的連線。也就是原始碼裡的go c.serve(ctx)。這一個步驟在 c.serve(ctx) 它並不是簡單的形式:

請求-->處理請求-->返回結果-->斷開這個連線-->結束當前的 gorutine

根據我的除錯結果原始碼分析顯示,正確的形式是下面這樣的:

  1. 為每一個連線的使用者啟動了一個長連線,serve 方法內部有個超時的設定是c.rwc.SetReadDeadline(time.Time{}),這樣子的情況,如果內部不出錯,當前的連線斷開的條件是客戶端自己斷開,或nat超時。

  2. 這個連線建立後,以ip為單位,當前的客戶端,此時它的所有http請求,例如getpost,它們都會在這個啟動的gorutine 內進行分發被處理

  3. 也就是說,同一個ip,多個不同的請求,這裡不會觸發另一個 accept,不會再去啟動一個go c.serve(ctx)

上述我們得出結論:

  1. 如果有 100萬

    accept,就證明有100萬個連線,100萬ip與當前server連線。即是我們說的百萬連線

  2. 百萬連線 不是百萬請求

  3. 每一個連線,它可以進行多個http請求,它的請求都在當前啟動這個連線的gorutine裡面進行。

  4. c.serve(...) 原始碼中的for 死迴圈就是負責讀取每個請求再分發
for {
    w, err := c.readRequest(ctx) // 讀取一個 http 請求
    //...
    ServeHTTP(...)
}
  1. 我們的100萬 連線裡面,有可能併發更多的請求,例如幾百萬請求,一個客戶端快速呼叫多個請求api

圖解總結

結合 master-worker 併發模式

根據我們上面的分析,每一個新連線到來,go 就會啟動一個 gorutine,在原始碼裡面也沒有看到有一個量級的限制,也就是達到多少連線就不再接收。我們也知道,伺服器是有處理瓶頸的。

所以,在這裡插播一個優化點,就是在server.go 內部做一個連線數目的限制。

master-worker 模式本身是啟動多個worker 執行緒,去併發讀取有界佇列裡面的任務,並執行。

我自身已經實現了一個go版本master-worker,做過下面的嘗試:

  1. go c.serve(ctx) 處做修改,如下。
if srv.masterWorkerModel {
    // lgh --- way to execute
    PoolMaster.AddJob(
        masterworker.Job{
            Tag:" http server ",
            Handler: func() {
                c.serve(ctx)
                fmt.Println("finish job") // 這一句在當前 ip 斷開連線後才會輸出
            },
        })
}else{
    go c.serve(ctx)
}

func (m Master) AddJob(job Job)  {
    fmt.Println("add a job ")
    m.JobQueue <- job // jobQueue 是具備緩衝的
}
// worker
func (w Worker) startWork(master *Master)  {
    go func() {
        for {
            select {
                case job := <-master.JobQueue:
                    job.doJob(master)
            }
        }
    }()
}
// job
func (j Job) doJob(master *Master) {
    go func() {
        fmt.Println(j.Tag+" --- doing job...")
        j.Handler()
    }()
}

不難理解它的模式。

現在我們使用生產者--消費者模式進行假設,連線的產生生產者<-master.JobQueue消費者,因為每一次消費就是啟動一個處理的gorutine

因為我們在accept 一個請求到<-master.JobQueue,管道輸出一個的這個過程中,可以說是沒有耗時操作的,這個job,它很快就被輸出了管道。也就是說,消費很快,那麼實際的生產環境中,我們的worker工作協程啟動5~10個就有餘了。

考慮如果出現了消費跟不上的情況,那麼多出來的job將會被緩衝到channel裡面。這種情況可能出現的情景是:

短時間十萬+級別連線的建立,就會導致worker讀取不過來。不過,即使發生了,也是很快就取完的。因為間中的耗時幾乎可以忽略不計!

也就說,短時間大量連線的建立,它的瓶頸在佇列的緩衝數。但是即使瓶頸發生了,它又能很快被分發處理掉。所以說:

  • 我的這個第一點的嘗試的意義事實上沒有多大的。只不過是換了一種方式去分發go c.serve(ctx)

  1. 這個是第二種結合方式,把master-worker放置到ServeHTTP的分發階段。例如下面程式碼,是常見的http handler寫法,我們就可以巢狀進去。
func (x XHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)  {
    //...
    if x.MasterWorker {
        poolMaster.AddJob(master_worker.Job{
            Tag:"normal",
            XContext:xc,
            Handler: func(context model.XContext) {
                x.HandleFunc(w,r)
            },
        })
        return
    }
    x.HandleFunc(w,r)
    //...
}

這樣的話,我們就能控制所有連線的併發請求最大數。超出的將會進行排隊,等待被執行,而不會因為短時間 http 請求數目不受控暴增 而導致伺服器掛掉。

此外上述第二種還存在一個:讀,過早關閉問題,這個留給讀者嘗試解決。

相關推薦

Go http/server.go連線解析 如何結合 master-worker 併發模式提高單機併發能力

作者:林冠巨集 / 指尖下的幽靈 關於 server.go 原始碼的解析可以去搜下,已經有很多且還不錯的文章。 正文: 從我們啟動http.ListenAndServe(port,router)開始,server.go 內部最終在一個for 迴圈中的 accept 方法中不停地等待客戶端的連

VS2010SQL Server 2008 允許遠端連線的解決方法

             使用者在使用SQL Server 2008遠端連結時,可能會彈出如下對話方塊:        “在連結SQL伺服器時發生網路連結錯誤或特定例項錯誤。SQL伺服器不存在或者連結不成功。請驗證使用者名稱是否正確或SQL伺服器是否已經配置遠端連結功能。

Mac 上TFTP Server 軟件的使用

comm 執行 連接服務器 ttys0 app chmod mac htm link 1、TFTP協議 簡單文件傳輸協議Trivial File Transfer Protocol (TFTP)是一個基於UDP協議的簡單的、低開銷的文件傳輸協議,允許客戶端get或者put文

如何使用windows10的遠端桌面連線工具控制樹莓派

1.準備   安裝好最新版的樹莓派官方系統映象,準備一臺顯示器,一套滑鼠鍵盤,HDMI轉VGA線(一端連線樹莓派的HDMI一端連線顯示器的VGA介面)。   進入官網https://www.raspberrypi.org/downloads/下載Raspbian系統(下載系統時推薦下載RASPBIAN JES

myeclipse刪除server方法

          第一步:        檢視server中是否存在myeclipse tomcat;                第二步                開啟“Window”——“perferences”;                第三步:  

JSON介紹及Android最全面解析方法(Gson、ASorg.son、Jackson解析)

前言 今天,我們來介紹一下現今主流的資料交換格式-JSON! 目錄 定義 JavaScript Object Notation,JavaScript的物件表示法,是一種輕量級的文字資料交換格式。 作用 用於資料的標記、儲存

Android開發:JSON簡介及最全面解析方法(Gson、ASorg.json、Jackson解析)

目錄 JSON簡介&解析方法介紹.png 定義 JavaScript Object Notation,JavaScript的物件表示法,是一種輕量級的文字資料交換格式。 作用 用於資料的標記、儲存和傳輸。 特點 輕量級的文字資料交換格式 獨立於語言和平臺 具有自我描述性 讀寫速度快,解析簡單 語法

VS 2013 用SQL Server開啟已有資料庫

1.連結SQL Server伺服器 在SQL Server物件資源管理器中,右擊SQL Server,點選新增SQL Server 選擇其中一個如:(LocalDB)\v11.0 點選 Connect 2.連結本地已有SQL資料庫檔案 在伺服器資源管理器中右擊資料

eclipse項目轉移至IDEAIDEA tomcat報錯(ideatomcat版本太高)war包部署到win服務器idea提交git的總結

image push under 正常 回來 env acc nvi 雲上 eclipse導出項目到idea時,不要導出target; idea打開eclipse項目後,出現junit找不到的問題,原因是jar包缺失,而maven配置的低版本的junit

遠端連線區域網內的sql server 無法連線 錯誤解決方法

第一個錯誤"SQL Server 不存在或訪問被拒絕"通常是最複雜的,錯誤發生的原因比較多,需要檢查的方面也比較多 。一般說來,有以下幾種可能性:   1、SQL Server名稱或IP地址拼寫有誤;   2、伺服器端網路配置有誤;   3、客戶端網路配置有誤。   要解決這個問題,我們一般要遵循以

HTTP的請求報文解析 響應報文解析HTTP請求報文中 GET 和 POST的區別 和 URL解析

一、什麼是HTTP? HTTP是超文字傳輸協議 二、HTTP特點? (1)HTTP是無狀態協議; (2)HTTP是web服務使用的協議; (3)HTTP是基於TCP協議的; (4)HTTP的通訊方式是客戶端-伺服器模式,即C/S

go http client, http server

only lock nan ret str net con iou main Go語言中的HTTP client, server非常簡單。具體如下。 HTTP Server package main import ( "fmt" "htm

Go Web:的ServeMux multiplexer

ServeMux簡介 ServeMux扮演的角色是Multiplexer,它用來將將請求根據url路由給已註冊的handler。如下圖: 上圖中為3個路徑註冊了handler,一個是"/",另外兩個是"/hello"和"/world"。這表示訪問http://hostname/hello時,multi

Go語言net/http解析

首先來看一個用net/http包寫的web伺服器:兩個函式實現http伺服器package main import ( "fmt" "net/http" "strings" "log" ) func sayhelloName(w http.ResponseWrit

系統的Sql server連線測試工具

系統有一種檔案是可以在設定引數後測試是否能正確連結到對應的資料庫上的,很方便簡單,不過不太好的就是如果連線的是ms sqlserver資料庫時,通過“連線”選項卡,只能讀取預設的例項顯示在伺服器名稱下拉列表,不能顯示其他例項名稱,需要到“所有”選項卡去手動編輯“Data Source”的值。也不能自動生成連線

go語言net/http解析http body之坑

在Server端解析HTTP請求的時候, func ProcScaleOutReq(rsp http.ResponseWriter, req *http.Request) { req.ParseForm() //bodyStr := [1024]byte{

xml解析工具mashaller javaee解析

for writer length star 工具 進行 去掉m comm err 1.怎樣去掉Marshaller的格式化? : JAXBContext context = JAXBContext.newInstance(Entity.class);

安裝好SQL Server 2016,沒有SSMS 工具

sqlhttps://docs.microsoft.com/zh-cn/sql/ssms/sql-server-management-studio-changelog-ssms?view=sql-server-2016#previous-ssms-releases 安裝:SQL Server Manageme

關於CDH5.11.0kafka 0.10 bootstrap-server 無法消費

出現 指定 pre hit tst apache 10.2.2 來看 min 近日需要在項目用到kafka,然後本地使用cdh集成的kafka 進行安裝調試,以及些樣例代碼,sparkstreaming 相關調用kafka 的代碼使用的原始的api 而沒有走zook

關於 MongoDB SQL Server 通過本身工具實現數據快速遷移 及 註意事項 的探究

數據遷移工具 文件中 文件導入 原本 修改字段 信息 字符 變化 是否 背景介紹 隨著業務的發展、需求的變化,促使我們追求使用不同類型的數據庫,充分發揮其各自特性。如果決定采用新類型的數據庫,就需要將既有的數據遷移到新的數據庫中。在這類需求中,將SQL Server中的數據