golang:使用timingwheel進行大量ticker的最佳化

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

Ticker

最近的項目用go實現的伺服器需要掛載大量的socket串連。如何判斷串連是否還存活就是我們需要考慮的一個問題了。

通常情況下面,socket如果被用戶端正常close,伺服器是能檢測到的,但是如果用戶端突然拔掉網線,或者是斷電,那麼socket的狀態在伺服器看來可能仍然是established。而實際上該socket已經不可用了。

為了判斷串連是否可用,通常我們會用timer機制來定時檢測,在go裡面,這非常容易實現,如下:

ticker := time.NewTicker(60 * time.Second)for {    select {        case <-ticker.C:            if err := ping(); err != nil {                close()            }    }}

上面我們使用一個60s的ticker,定時去ping,如果ping失敗了,證明串連已經斷開了,這時候就需要close了。

這套機制比較簡單,也啟動並執行很好,直到我們的伺服器連上了10w+的串連。因為每一個串連都有一個ticker,所以同時會有大量的ticker運行,cpu一直在30%左右徘徊,效能不能讓人接受。

其實,我們只需要的是一套高效的逾時通知機制。

Close channel to broadcast

在go裡面,channel是一個很不錯的東西,我們可以通過close channel來進行broadcast。如下:

ch := make(bool)for i := 0; i < 10; i++ {    go func() {        println("begin")        <-ch        println("end")    }}time.Sleep(10 * time.Second)close(ch)

上面,我們啟動了10個goroutine,它們都會因為等待ch的資料而block,10s之後close這個channel,那麼所有等待該channel的goroutine就會繼續往下執行。

TimingWheel

通過channel這種close broadcast機制,我們可以非常方便的實現一個timer,timer有一個channel ch,所有需要在某一個時間 “T” 收到通知的goroutine都可以嘗試讀該ch,當T到達時候,close該ch,那麼所有的goroutine都能收到該事件了。

timingwheel的使用很簡單,首先我們建立一個wheel

//這裡我們建立了一個timingwheel,精度是1s,最大的逾時等待時間為3600sw := timingwheel.NewTimingWheel(1 * time.Second, 3600)//等待10s<-w.After(10 * time.Second)

因為timingwheel只有一個1s的ticker,並且只建立了3600個channel,系統開銷很小。當我們程式換上timingwheel之後,10w+串連cpu開銷在10%以下,達到了最佳化效果。

timingwheel的代碼在這裡。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.