fixed healthcheck failed to disable and nil dereference

This commit is contained in:
yusing 2024-10-19 00:13:55 +08:00
parent 53557e38b6
commit b296fb2965
11 changed files with 60 additions and 20 deletions

View file

@ -31,6 +31,7 @@ func NewHandler() http.Handler {
mux.HandleFunc("POST", "/v1/reload", v1.Reload)
mux.HandleFunc("GET", "/v1/list", v1.List)
mux.HandleFunc("GET", "/v1/list/{what}", v1.List)
mux.HandleFunc("GET", "/v1/list/{what}/{which}", v1.List)
mux.HandleFunc("GET", "/v1/file", v1.GetFileContent)
mux.HandleFunc("GET", "/v1/file/{filename...}", v1.GetFileContent)
mux.HandleFunc("POST", "/v1/file/{filename...}", v1.SetFileContent)

View file

@ -14,6 +14,7 @@ import (
)
const (
ListRoute = "route"
ListRoutes = "routes"
ListConfigFiles = "config_files"
ListMiddlewares = "middlewares"
@ -28,8 +29,16 @@ func List(w http.ResponseWriter, r *http.Request) {
if what == "" {
what = ListRoutes
}
which := r.PathValue("which")
switch what {
case ListRoute:
if route := listRoute(which); route == nil {
http.Error(w, "not found", http.StatusNotFound)
return
} else {
U.RespondJSON(w, r, route)
}
case ListRoutes:
U.RespondJSON(w, r, config.RoutesByAlias(route.RouteType(r.FormValue("type"))))
case ListConfigFiles:
@ -49,6 +58,21 @@ func List(w http.ResponseWriter, r *http.Request) {
}
}
func listRoute(which string) any {
if which == "" {
which = "all"
}
if which == "all" {
return config.RoutesByAlias()
}
routes := config.RoutesByAlias()
route, ok := routes[which]
if !ok {
return nil
}
return route
}
func listConfigFiles(w http.ResponseWriter, r *http.Request) {
files, err := utils.ListFiles(common.ConfigBasePath, 1)
if err != nil {

View file

@ -64,5 +64,5 @@ func UseIdleWatcher(entry Entry) bool {
func UseHealthCheck(entry Entry) bool {
hc := entry.HealthCheckConfig()
return hc != nil && !hc.Disabled
return hc != nil && !hc.Disable
}

View file

@ -126,15 +126,15 @@ func (e *RawEntry) FillMissingFields() {
e.HealthCheck = new(health.HealthCheckConfig)
}
if e.HealthCheck.Disabled {
if e.HealthCheck.Interval == 0 {
e.HealthCheck.Interval = common.HealthCheckIntervalDefault
}
if e.HealthCheck.Timeout == 0 {
e.HealthCheck.Timeout = common.HealthCheckTimeoutDefault
}
if e.HealthCheck.Disable {
e.HealthCheck = nil
} else {
if e.HealthCheck.Interval == 0 {
e.HealthCheck.Interval = common.HealthCheckIntervalDefault
}
if e.HealthCheck.Timeout == 0 {
e.HealthCheck.Timeout = common.HealthCheckTimeoutDefault
}
}
if cont.IdleTimeout != "" {

View file

@ -106,9 +106,12 @@ func (r *HTTPRoute) Start(providerSubtask task.Task) E.NestedError {
httpRoutesMu.Lock()
defer httpRoutesMu.Unlock()
if r.HealthCheck.Disabled && (entry.UseLoadBalance(r) || entry.UseIdleWatcher(r)) {
if !entry.UseHealthCheck(r) && (entry.UseLoadBalance(r) || entry.UseIdleWatcher(r)) {
logrus.Warnf("%s.healthCheck.disabled cannot be false when loadbalancer or idlewatcher is enabled", r.Alias)
r.HealthCheck.Disabled = true
if r.HealthCheck == nil {
r.HealthCheck = new(health.HealthCheckConfig)
}
r.HealthCheck.Disable = true
}
switch {
@ -121,6 +124,7 @@ func (r *HTTPRoute) Start(providerSubtask task.Task) E.NestedError {
r.handler = waker
r.HealthMon = waker
case entry.UseHealthCheck(r):
logrus.Debugf("%s health check: %+v", r.Alias, r.HealthCheck)
r.HealthMon = health.NewHTTPHealthMonitor(r.TargetURL(), r.HealthCheck, r.rp.Transport)
}
r.task = providerSubtask

View file

@ -61,6 +61,8 @@ func (p *FileProvider) LoadRoutesImpl() (routes R.Routes, res E.NestedError) {
return
}
b.Add(Validate(data))
return R.FromEntries(entries)
}

View file

@ -66,9 +66,9 @@ func (r *StreamRoute) Start(providerSubtask task.Task) E.NestedError {
streamRoutesMu.Lock()
defer streamRoutesMu.Unlock()
if r.HealthCheck.Disabled && (entry.UseLoadBalance(r) || entry.UseIdleWatcher(r)) {
if r.HealthCheck.Disable && (entry.UseLoadBalance(r) || entry.UseIdleWatcher(r)) {
logrus.Warnf("%s.healthCheck.disabled cannot be false when loadbalancer or idlewatcher is enabled", r.Alias)
r.HealthCheck.Disabled = true
r.HealthCheck.Disable = true
}
if r.Scheme.ListeningScheme.IsTCP() {

View file

@ -160,7 +160,11 @@ func (t *task) Context() context.Context {
}
func (t *task) FinishCause() error {
return context.Cause(t.ctx)
cause := context.Cause(t.ctx)
if cause == nil {
return t.ctx.Err()
}
return cause
}
func (t *task) Parent() Task {

View file

@ -7,7 +7,7 @@ import (
)
type HealthCheckConfig struct {
Disabled bool `json:"disabled,omitempty" yaml:"disabled"`
Disable bool `json:"disable,omitempty" yaml:"disable"`
Path string `json:"path,omitempty" yaml:"path"`
UseGet bool `json:"use_get,omitempty" yaml:"use_get"`
Interval time.Duration `json:"interval" yaml:"interval"`

View file

@ -75,20 +75,25 @@ func (mon *monitor) Start(routeSubtask task.Task) E.NestedError {
mon.service = routeSubtask.Parent().Name()
mon.task = routeSubtask
if err := mon.checkUpdateHealth(); err != nil {
mon.task.Finish(fmt.Sprintf("healthchecker %s failure: %s", mon.service, err))
return err
if mon.config.Interval <= 0 {
return E.Invalid("interval", mon.config.Interval)
}
go func() {
defer func() {
monMap.Delete(mon.task.Name())
if mon.status.Load() != StatusError {
mon.status.Store(StatusUnknown)
}
mon.task.Finish(mon.task.FinishCause().Error())
}()
if err := mon.checkUpdateHealth(); err != nil {
logger.Errorf("healthchecker %s failure: %s", mon.service, err)
return
}
monMap.Store(mon.service, mon)
defer monMap.Delete(mon.service)
ticker := time.NewTicker(mon.config.Interval)
defer ticker.Stop()

View file

@ -149,7 +149,7 @@
"healthcheck": {
"type": "object",
"properties": {
"disabled": {
"disable": {
"type": "boolean",
"default": false
},