67 lines
1.6 KiB
Go
67 lines
1.6 KiB
Go
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)
|
|
}
|
|
}()
|
|
}
|