refactor health module

This commit is contained in:
yusing 2024-11-13 06:46:01 +08:00
parent 6a2638c70c
commit f3b21e6bd9
9 changed files with 37 additions and 29 deletions

View file

@ -15,6 +15,7 @@ import (
"github.com/yusing/go-proxy/internal/task" "github.com/yusing/go-proxy/internal/task"
U "github.com/yusing/go-proxy/internal/utils" U "github.com/yusing/go-proxy/internal/utils"
"github.com/yusing/go-proxy/internal/watcher/health" "github.com/yusing/go-proxy/internal/watcher/health"
"github.com/yusing/go-proxy/internal/watcher/health/monitor"
) )
type waker struct { type waker struct {
@ -51,9 +52,9 @@ func newWaker(providerSubTask task.Task, entry entry.Entry, rp *gphttp.ReversePr
switch { switch {
case rp != nil: case rp != nil:
waker.hc = health.NewHTTPHealthChecker(entry.TargetURL(), hcCfg) waker.hc = monitor.NewHTTPHealthChecker(entry.TargetURL(), hcCfg)
case stream != nil: case stream != nil:
waker.hc = health.NewRawHealthChecker(entry.TargetURL(), hcCfg) waker.hc = monitor.NewRawHealthChecker(entry.TargetURL(), hcCfg)
default: default:
panic("both nil") panic("both nil")
} }
@ -147,7 +148,7 @@ func (w *Watcher) MarshalJSON() ([]byte, error) {
if w.hc.URL().Port() != "0" { if w.hc.URL().Port() != "0" {
url = w.hc.URL() url = w.hc.URL()
} }
return (&health.JSONRepresentation{ return (&monitor.JSONRepresentation{
Name: w.Name(), Name: w.Name(),
Status: w.Status(), Status: w.Status(),
Config: w.hc.Config(), Config: w.hc.Config(),

View file

@ -12,6 +12,7 @@ import (
"github.com/yusing/go-proxy/internal/net/http/middleware" "github.com/yusing/go-proxy/internal/net/http/middleware"
"github.com/yusing/go-proxy/internal/task" "github.com/yusing/go-proxy/internal/task"
"github.com/yusing/go-proxy/internal/watcher/health" "github.com/yusing/go-proxy/internal/watcher/health"
"github.com/yusing/go-proxy/internal/watcher/health/monitor"
) )
// TODO: stats of each server. // TODO: stats of each server.
@ -248,7 +249,7 @@ func (lb *LoadBalancer) MarshalJSON() ([]byte, error) {
extra[v.Name] = v.healthMon extra[v.Name] = v.healthMon
}) })
return (&health.JSONRepresentation{ return (&monitor.JSONRepresentation{
Name: lb.Name(), Name: lb.Name(),
Status: lb.Status(), Status: lb.Status(),
Started: lb.startTime, Started: lb.startTime,

View file

@ -19,6 +19,7 @@ import (
"github.com/yusing/go-proxy/internal/task" "github.com/yusing/go-proxy/internal/task"
F "github.com/yusing/go-proxy/internal/utils/functional" F "github.com/yusing/go-proxy/internal/utils/functional"
"github.com/yusing/go-proxy/internal/watcher/health" "github.com/yusing/go-proxy/internal/watcher/health"
"github.com/yusing/go-proxy/internal/watcher/health/monitor"
) )
type ( type (
@ -111,7 +112,7 @@ func (r *HTTPRoute) Start(providerSubtask task.Task) E.Error {
r.handler = waker r.handler = waker
r.HealthMon = waker r.HealthMon = waker
case entry.UseHealthCheck(r): case entry.UseHealthCheck(r):
r.HealthMon = health.NewHTTPHealthMonitor(r.rp.TargetURL, r.HealthCheck) r.HealthMon = monitor.NewHTTPHealthMonitor(r.rp.TargetURL, r.HealthCheck)
} }
if r.handler == nil { if r.handler == nil {

View file

@ -13,6 +13,7 @@ import (
"github.com/yusing/go-proxy/internal/task" "github.com/yusing/go-proxy/internal/task"
F "github.com/yusing/go-proxy/internal/utils/functional" F "github.com/yusing/go-proxy/internal/utils/functional"
"github.com/yusing/go-proxy/internal/watcher/health" "github.com/yusing/go-proxy/internal/watcher/health"
"github.com/yusing/go-proxy/internal/watcher/health/monitor"
) )
type StreamRoute struct { type StreamRoute struct {
@ -72,7 +73,7 @@ func (r *StreamRoute) Start(providerSubtask task.Task) E.Error {
r.stream = waker r.stream = waker
r.HealthMon = waker r.HealthMon = waker
case entry.UseHealthCheck(r): case entry.UseHealthCheck(r):
r.HealthMon = health.NewRawHealthMonitor(r.TargetURL(), r.HealthCheck) r.HealthMon = monitor.NewRawHealthMonitor(r.TargetURL(), r.HealthCheck)
} }
if err := r.stream.Setup(); err != nil { if err := r.stream.Setup(); err != nil {

View file

@ -1,4 +1,4 @@
package health package monitor
import ( import (
"crypto/tls" "crypto/tls"
@ -6,6 +6,7 @@ import (
"net/http" "net/http"
"github.com/yusing/go-proxy/internal/net/types" "github.com/yusing/go-proxy/internal/net/types"
"github.com/yusing/go-proxy/internal/watcher/health"
"github.com/yusing/go-proxy/pkg" "github.com/yusing/go-proxy/pkg"
) )
@ -24,7 +25,7 @@ var pinger = &http.Client{
}, },
} }
func NewHTTPHealthMonitor(url types.URL, config *HealthCheckConfig) *HTTPHealthMonitor { func NewHTTPHealthMonitor(url types.URL, config *health.HealthCheckConfig) *HTTPHealthMonitor {
mon := new(HTTPHealthMonitor) mon := new(HTTPHealthMonitor)
mon.monitor = newMonitor(url, config, mon.CheckHealth) mon.monitor = newMonitor(url, config, mon.CheckHealth)
if config.UseGet { if config.UseGet {
@ -35,7 +36,7 @@ func NewHTTPHealthMonitor(url types.URL, config *HealthCheckConfig) *HTTPHealthM
return mon return mon
} }
func NewHTTPHealthChecker(url types.URL, config *HealthCheckConfig) HealthChecker { func NewHTTPHealthChecker(url types.URL, config *health.HealthCheckConfig) health.HealthChecker {
return NewHTTPHealthMonitor(url, config) return NewHTTPHealthMonitor(url, config)
} }

View file

@ -1,4 +1,4 @@
package health package monitor
import ( import (
"encoding/json" "encoding/json"
@ -6,12 +6,13 @@ import (
"github.com/yusing/go-proxy/internal/net/types" "github.com/yusing/go-proxy/internal/net/types"
"github.com/yusing/go-proxy/internal/utils/strutils" "github.com/yusing/go-proxy/internal/utils/strutils"
"github.com/yusing/go-proxy/internal/watcher/health"
) )
type JSONRepresentation struct { type JSONRepresentation struct {
Name string Name string
Config *HealthCheckConfig Config *health.HealthCheckConfig
Status Status Status health.Status
Started time.Time Started time.Time
Uptime time.Duration Uptime time.Duration
URL types.URL URL types.URL

View file

@ -1,4 +1,4 @@
package health package monitor
import ( import (
"context" "context"
@ -16,16 +16,17 @@ import (
"github.com/yusing/go-proxy/internal/notif" "github.com/yusing/go-proxy/internal/notif"
"github.com/yusing/go-proxy/internal/task" "github.com/yusing/go-proxy/internal/task"
U "github.com/yusing/go-proxy/internal/utils" U "github.com/yusing/go-proxy/internal/utils"
"github.com/yusing/go-proxy/internal/watcher/health"
) )
type ( type (
HealthCheckFunc func() (healthy bool, detail string, err error) HealthCheckFunc func() (healthy bool, detail string, err error)
monitor struct { monitor struct {
service string service string
config *HealthCheckConfig config *health.HealthCheckConfig
url U.AtomicValue[types.URL] url U.AtomicValue[types.URL]
status U.AtomicValue[Status] status U.AtomicValue[health.Status]
checkHealth HealthCheckFunc checkHealth HealthCheckFunc
startTime time.Time startTime time.Time
@ -37,14 +38,14 @@ type (
var ErrNegativeInterval = errors.New("negative interval") var ErrNegativeInterval = errors.New("negative interval")
func newMonitor(url types.URL, config *HealthCheckConfig, healthCheckFunc HealthCheckFunc) *monitor { func newMonitor(url types.URL, config *health.HealthCheckConfig, healthCheckFunc HealthCheckFunc) *monitor {
mon := &monitor{ mon := &monitor{
config: config, config: config,
checkHealth: healthCheckFunc, checkHealth: healthCheckFunc,
startTime: time.Now(), startTime: time.Now(),
} }
mon.url.Store(url) mon.url.Store(url)
mon.status.Store(StatusHealthy) mon.status.Store(health.StatusHealthy)
return mon return mon
} }
@ -72,8 +73,8 @@ func (mon *monitor) Start(routeSubtask task.Task) E.Error {
logger := logging.With().Str("name", mon.service).Logger() logger := logging.With().Str("name", mon.service).Logger()
defer func() { defer func() {
if mon.status.Load() != StatusError { if mon.status.Load() != health.StatusError {
mon.status.Store(StatusUnknown) mon.status.Store(health.StatusUnknown)
} }
mon.task.Finish(nil) mon.task.Finish(nil)
if mon.metric != nil { if mon.metric != nil {
@ -121,12 +122,12 @@ func (mon *monitor) URL() types.URL {
} }
// Config implements HealthChecker. // Config implements HealthChecker.
func (mon *monitor) Config() *HealthCheckConfig { func (mon *monitor) Config() *health.HealthCheckConfig {
return mon.config return mon.config
} }
// Status implements HealthMonitor. // Status implements HealthMonitor.
func (mon *monitor) Status() Status { func (mon *monitor) Status() health.Status {
return mon.status.Load() return mon.status.Load()
} }
@ -163,19 +164,19 @@ func (mon *monitor) checkUpdateHealth() error {
healthy, detail, err := mon.checkHealth() healthy, detail, err := mon.checkHealth()
if err != nil { if err != nil {
defer mon.task.Finish(err) defer mon.task.Finish(err)
mon.status.Store(StatusError) mon.status.Store(health.StatusError)
if !errors.Is(err, context.Canceled) { if !errors.Is(err, context.Canceled) {
return fmt.Errorf("check health: %w", err) return fmt.Errorf("check health: %w", err)
} }
return nil return nil
} }
var status Status var status health.Status
if healthy { if healthy {
status = StatusHealthy status = health.StatusHealthy
} else { } else {
status = StatusUnhealthy status = health.StatusUnhealthy
} }
if healthy != (mon.status.Swap(status) == StatusHealthy) { if healthy != (mon.status.Swap(status) == health.StatusHealthy) {
if healthy { if healthy {
logger.Info().Msg("server is up") logger.Info().Msg("server is up")
notif.Notify(mon.service, "server is up") notif.Notify(mon.service, "server is up")

View file

@ -1,9 +1,10 @@
package health package monitor
import ( import (
"net" "net"
"github.com/yusing/go-proxy/internal/net/types" "github.com/yusing/go-proxy/internal/net/types"
"github.com/yusing/go-proxy/internal/watcher/health"
) )
type ( type (
@ -13,7 +14,7 @@ type (
} }
) )
func NewRawHealthMonitor(url types.URL, config *HealthCheckConfig) *RawHealthMonitor { func NewRawHealthMonitor(url types.URL, config *health.HealthCheckConfig) *RawHealthMonitor {
mon := new(RawHealthMonitor) mon := new(RawHealthMonitor)
mon.monitor = newMonitor(url, config, mon.CheckHealth) mon.monitor = newMonitor(url, config, mon.CheckHealth)
mon.dialer = &net.Dialer{ mon.dialer = &net.Dialer{
@ -23,7 +24,7 @@ func NewRawHealthMonitor(url types.URL, config *HealthCheckConfig) *RawHealthMon
return mon return mon
} }
func NewRawHealthChecker(url types.URL, config *HealthCheckConfig) HealthChecker { func NewRawHealthChecker(url types.URL, config *health.HealthCheckConfig) health.HealthChecker {
return NewRawHealthMonitor(url, config) return NewRawHealthMonitor(url, config)
} }