Goroutine心跳檢測

Goroutine心跳檢測

心跳檢測的核心思想是,單獨啓動心跳協程,然後通過向協程發送數據,表示心跳。

package main
import (
    "fmt"
    "math/rand"
    "time"
)
func main() {
    rand.Seed(time.Now().UnixNano())
    doWork := func(done <-chan interface{},
        pulseInterval time.Duration,
        genData func() interface{},
    ) (<-chan interface{}, <-chan interface{}) {
        heartBeat := make(chan interface{}) // 心跳
        results := make(chan interface{})
        go func() {
            defer close(heartBeat)
            defer close(results)
            sendPulse := func() {
                select {
                case heartBeat <- struct{}{}:
                default: // 心跳不一定有人接收
                }
            }
            pulse := time.Tick(pulseInterval)
            sendResult := func(r interface{}) {
                for {
                    select {
                    case <-done:
                        return
                    case <-pulse: // 接收channel可能阻塞,因此持續心跳
                        sendPulse()
                    case results <- r:
                        return // 耗時任務完成後,立刻返回
                    }
                }
            }
            bridge := make(chan interface{})
            go func() {
                defer close(res)
                bridge <- genData()  // 我們假設會一直等到有數據發送過來
            }()
            for {
                select {
                case <-done:
                    return
                case <-pulse:
                    sendPulse()
                case r, ok := <-res:
                    if !ok { // 前邊有關掉res了,所以這裏需要ok判斷
                        return
                    }
                    sendResult(r)
                }
            }
        }()
        return heartBeat, results
    }
    genMyData := func() interface{} {
        t := rand.Intn(10) + 3
        time.Sleep(time.Second * time.Duration(t))
        fmt.Printf("genMyData weak up after:%v\n", t)
        return "foo"
    }
    done := make(chan interface{})
    defer close(done)
    interval := time.Second
    heatBeat, result := doWork(done,interval, genMyData)
    for {
        select {
        case _, ok := <-heatBeat:
            if !ok {
                return
            }
            fmt.Println("hearbeat")
        case r, ok := <-result:
            if !ok {
                return
            }
            fmt.Printf("get result: %v\n", r)
        case <-time.After(interval * 2):  // 2倍心跳時間找不到心跳信號,則認爲超時
            fmt.Printf("timeout")
            return
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章