package healthcheck import ( "fmt" "net/http" "time" "git.pyer.club/kingecg/gologger" ) // HealthChecker 健康检查器 type HealthChecker struct { client *http.Client interval time.Duration timeout time.Duration retries int } func NewHealthChecker(interval time.Duration, timeout time.Duration, retries int) *HealthChecker { return &HealthChecker{ client: &http.Client{ Timeout: timeout, }, interval: interval, timeout: timeout, retries: retries, } } // CheckHealth 检查上游服务器健康状态 func (hc *HealthChecker) CheckHealth(url string) bool { logger := gologger.GetLogger("healthcheck") for i := 0; i < hc.retries; i++ { resp, err := hc.client.Get(url + "/health") if err == nil && resp.StatusCode == http.StatusOK { return true } logger.Warn(fmt.Sprintf("Health check failed for %s: %v", url, err)) time.Sleep(hc.timeout) } logger.Error(fmt.Sprintf("All health checks failed for %s", url)) return false } // StartHealthCheck 启动健康检查协程 func (hc *HealthChecker) StartHealthCheck(upstreams []string, onStatusChange func(string, bool)) { logger := gologger.GetLogger("healthcheck") go func() { statusMap := make(map[string]bool) for { for _, upstream := range upstreams { healthy := hc.CheckHealth(upstream) if status, exists := statusMap[upstream]; exists { if status != healthy { logger.Info(fmt.Sprintf("Upstream %s status changed to %v", upstream, healthy)) if onStatusChange != nil { onStatusChange(upstream, healthy) } } } statusMap[upstream] = healthy } time.Sleep(hc.interval) } }() }