golang select結構經典應用

###應用場景mysql

前幾天領導交給我一項任務,讓我監控某項服務是否啓動成功,當時我想就沒想就接下了,回來以後考慮了N多種方案。大體分爲2類

###1、主動golang

就是把自身信息主動推上去,如服務啓動後把自身信息註冊到zookeeper,這樣調用zookeeper的api就能夠看到sql

###2、被動api

使用輪詢方式拉取服務狀態,如使用定時器或for循環主動去獲取服務器狀態,固然這種方式並非永無止境的,要設置一個臨值服務器

使用定時器和for循環這種方式我以爲有點太老套,下面我就結合golang 當中的 select 和goroutine來實現。tcp

//如檢測mysql是否鏈路是否暢通
func () testConn(host, port string) error {
	ch := make(chan int, 1)    //定義一個帶緩衝通道的goroutine
	go func() {
		var err error
		var c net.Conn
		for {
			c, err = net.DialTimeout("tcp", "localhost:3306", 20 * time.Second)
                    //若是err ==nil 就表明鏈路是暢通的,此時退出就能夠了
			if err == nil {
				c.Close()
				ch <- 1//隨便向通道里放一個int類型的值就能夠
			} else {
                                //若是鏈路不一樣,就休眠兩秒繼續檢測
				log.Errorf("failed to connect to db, retry after 2 seconds :%v", err)
				time.Sleep(2 * time.Second) //休眠兩秒
			}
		}
	}()
    //select 會監聽routine的數據流動,若是有就退出,不然會等待超時(也就是60秒)
	select {
	    case <-ch: //有數據就退出
		    return nil
	    case <-time.After(60 * time.Second): //若是等待60秒尚未監聽到ch當中有數據流動就拋出異常,程序結束
		return errors.New("failed to connect to database after 60 seconds")
	}
}

###總結:主動方式要比輪詢方式效率高不少,要結合本身的實際狀況來選擇。code

相關文章
相關標籤/搜索