package client import ( "container/heap" "github.com/cnlh/nps/lib/conn" "github.com/cnlh/nps/lib/file" "github.com/cnlh/nps/lib/sheap" "github.com/cnlh/nps/vender/github.com/astaxie/beego/logs" "github.com/pkg/errors" "net" "net/http" "strings" "time" ) var isStart bool var serverConn *conn.Conn func heathCheck(healths []*file.Health, c *conn.Conn) bool { serverConn = c if isStart { for _, v := range healths { v.HealthMap = make(map[string]int) } return true } isStart = true h := &sheap.IntHeap{} for _, v := range healths { if v.HealthMaxFail > 0 && v.HealthCheckTimeout > 0 && v.HealthCheckInterval > 0 { v.HealthNextTime = time.Now().Add(time.Duration(v.HealthCheckInterval) * time.Second) heap.Push(h, v.HealthNextTime.Unix()) v.HealthMap = make(map[string]int) } } go session(healths, h) return true } func session(healths []*file.Health, h *sheap.IntHeap) { for { if h.Len() == 0 { logs.Error("health check error") break } rs := heap.Pop(h).(int64) - time.Now().Unix() if rs <= 0 { continue } timer := time.NewTimer(time.Duration(rs) * time.Second) select { case <-timer.C: for _, v := range healths { if v.HealthNextTime.Before(time.Now()) { v.HealthNextTime = time.Now().Add(time.Duration(v.HealthCheckInterval) * time.Second) //check go check(v) //reset time heap.Push(h, v.HealthNextTime.Unix()) } } } } } //只针对一个端口 面向多个目标的情况 func check(t *file.Health) { arr := strings.Split(t.HealthCheckTarget, ",") var err error var rs *http.Response for _, v := range arr { if t.HealthCheckType == "tcp" { _, err = net.DialTimeout("tcp", v, time.Duration(t.HealthCheckTimeout)*time.Second); } else { client := &http.Client{} client.Timeout = time.Duration(t.HealthCheckTimeout) * time.Second rs, err = client.Get("http://" + v + t.HttpHealthUrl) if err == nil && rs.StatusCode != 200 { err = errors.New("status code is not match") } } if err != nil { t.HealthMap[v] += 1 } else if t.HealthMap[v] >= t.HealthMaxFail { //send recovery add serverConn.SendHealthInfo(v, "1") t.HealthMap[v] = 0 } if t.HealthMap[v] == t.HealthMaxFail { //send fail remove serverConn.SendHealthInfo(v, "0") } } }