mirror of
https://github.com/yusing/godoxy.git
synced 2025-07-09 07:54:03 +02:00
fixed healthcheck failed to disable and nil dereference
This commit is contained in:
parent
53557e38b6
commit
b296fb2965
11 changed files with 60 additions and 20 deletions
|
@ -31,6 +31,7 @@ func NewHandler() http.Handler {
|
||||||
mux.HandleFunc("POST", "/v1/reload", v1.Reload)
|
mux.HandleFunc("POST", "/v1/reload", v1.Reload)
|
||||||
mux.HandleFunc("GET", "/v1/list", v1.List)
|
mux.HandleFunc("GET", "/v1/list", v1.List)
|
||||||
mux.HandleFunc("GET", "/v1/list/{what}", 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", v1.GetFileContent)
|
||||||
mux.HandleFunc("GET", "/v1/file/{filename...}", v1.GetFileContent)
|
mux.HandleFunc("GET", "/v1/file/{filename...}", v1.GetFileContent)
|
||||||
mux.HandleFunc("POST", "/v1/file/{filename...}", v1.SetFileContent)
|
mux.HandleFunc("POST", "/v1/file/{filename...}", v1.SetFileContent)
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
ListRoute = "route"
|
||||||
ListRoutes = "routes"
|
ListRoutes = "routes"
|
||||||
ListConfigFiles = "config_files"
|
ListConfigFiles = "config_files"
|
||||||
ListMiddlewares = "middlewares"
|
ListMiddlewares = "middlewares"
|
||||||
|
@ -28,8 +29,16 @@ func List(w http.ResponseWriter, r *http.Request) {
|
||||||
if what == "" {
|
if what == "" {
|
||||||
what = ListRoutes
|
what = ListRoutes
|
||||||
}
|
}
|
||||||
|
which := r.PathValue("which")
|
||||||
|
|
||||||
switch what {
|
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:
|
case ListRoutes:
|
||||||
U.RespondJSON(w, r, config.RoutesByAlias(route.RouteType(r.FormValue("type"))))
|
U.RespondJSON(w, r, config.RoutesByAlias(route.RouteType(r.FormValue("type"))))
|
||||||
case ListConfigFiles:
|
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) {
|
func listConfigFiles(w http.ResponseWriter, r *http.Request) {
|
||||||
files, err := utils.ListFiles(common.ConfigBasePath, 1)
|
files, err := utils.ListFiles(common.ConfigBasePath, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -64,5 +64,5 @@ func UseIdleWatcher(entry Entry) bool {
|
||||||
|
|
||||||
func UseHealthCheck(entry Entry) bool {
|
func UseHealthCheck(entry Entry) bool {
|
||||||
hc := entry.HealthCheckConfig()
|
hc := entry.HealthCheckConfig()
|
||||||
return hc != nil && !hc.Disabled
|
return hc != nil && !hc.Disable
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,15 +126,15 @@ func (e *RawEntry) FillMissingFields() {
|
||||||
e.HealthCheck = new(health.HealthCheckConfig)
|
e.HealthCheck = new(health.HealthCheckConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.HealthCheck.Disabled {
|
|
||||||
e.HealthCheck = nil
|
|
||||||
} else {
|
|
||||||
if e.HealthCheck.Interval == 0 {
|
if e.HealthCheck.Interval == 0 {
|
||||||
e.HealthCheck.Interval = common.HealthCheckIntervalDefault
|
e.HealthCheck.Interval = common.HealthCheckIntervalDefault
|
||||||
}
|
}
|
||||||
if e.HealthCheck.Timeout == 0 {
|
if e.HealthCheck.Timeout == 0 {
|
||||||
e.HealthCheck.Timeout = common.HealthCheckTimeoutDefault
|
e.HealthCheck.Timeout = common.HealthCheckTimeoutDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if e.HealthCheck.Disable {
|
||||||
|
e.HealthCheck = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if cont.IdleTimeout != "" {
|
if cont.IdleTimeout != "" {
|
||||||
|
|
|
@ -106,9 +106,12 @@ func (r *HTTPRoute) Start(providerSubtask task.Task) E.NestedError {
|
||||||
httpRoutesMu.Lock()
|
httpRoutesMu.Lock()
|
||||||
defer httpRoutesMu.Unlock()
|
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)
|
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 {
|
switch {
|
||||||
|
@ -121,6 +124,7 @@ func (r *HTTPRoute) Start(providerSubtask task.Task) E.NestedError {
|
||||||
r.handler = waker
|
r.handler = waker
|
||||||
r.HealthMon = waker
|
r.HealthMon = waker
|
||||||
case entry.UseHealthCheck(r):
|
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.HealthMon = health.NewHTTPHealthMonitor(r.TargetURL(), r.HealthCheck, r.rp.Transport)
|
||||||
}
|
}
|
||||||
r.task = providerSubtask
|
r.task = providerSubtask
|
||||||
|
|
|
@ -61,6 +61,8 @@ func (p *FileProvider) LoadRoutesImpl() (routes R.Routes, res E.NestedError) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b.Add(Validate(data))
|
||||||
|
|
||||||
return R.FromEntries(entries)
|
return R.FromEntries(entries)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,9 +66,9 @@ func (r *StreamRoute) Start(providerSubtask task.Task) E.NestedError {
|
||||||
streamRoutesMu.Lock()
|
streamRoutesMu.Lock()
|
||||||
defer streamRoutesMu.Unlock()
|
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)
|
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() {
|
if r.Scheme.ListeningScheme.IsTCP() {
|
||||||
|
|
|
@ -160,7 +160,11 @@ func (t *task) Context() context.Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *task) FinishCause() error {
|
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 {
|
func (t *task) Parent() Task {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type HealthCheckConfig struct {
|
type HealthCheckConfig struct {
|
||||||
Disabled bool `json:"disabled,omitempty" yaml:"disabled"`
|
Disable bool `json:"disable,omitempty" yaml:"disable"`
|
||||||
Path string `json:"path,omitempty" yaml:"path"`
|
Path string `json:"path,omitempty" yaml:"path"`
|
||||||
UseGet bool `json:"use_get,omitempty" yaml:"use_get"`
|
UseGet bool `json:"use_get,omitempty" yaml:"use_get"`
|
||||||
Interval time.Duration `json:"interval" yaml:"interval"`
|
Interval time.Duration `json:"interval" yaml:"interval"`
|
||||||
|
|
|
@ -75,20 +75,25 @@ func (mon *monitor) Start(routeSubtask task.Task) E.NestedError {
|
||||||
mon.service = routeSubtask.Parent().Name()
|
mon.service = routeSubtask.Parent().Name()
|
||||||
mon.task = routeSubtask
|
mon.task = routeSubtask
|
||||||
|
|
||||||
if err := mon.checkUpdateHealth(); err != nil {
|
if mon.config.Interval <= 0 {
|
||||||
mon.task.Finish(fmt.Sprintf("healthchecker %s failure: %s", mon.service, err))
|
return E.Invalid("interval", mon.config.Interval)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer func() {
|
defer func() {
|
||||||
monMap.Delete(mon.task.Name())
|
|
||||||
if mon.status.Load() != StatusError {
|
if mon.status.Load() != StatusError {
|
||||||
mon.status.Store(StatusUnknown)
|
mon.status.Store(StatusUnknown)
|
||||||
}
|
}
|
||||||
mon.task.Finish(mon.task.FinishCause().Error())
|
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)
|
monMap.Store(mon.service, mon)
|
||||||
|
defer monMap.Delete(mon.service)
|
||||||
|
|
||||||
ticker := time.NewTicker(mon.config.Interval)
|
ticker := time.NewTicker(mon.config.Interval)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
|
@ -149,7 +149,7 @@
|
||||||
"healthcheck": {
|
"healthcheck": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"disabled": {
|
"disable": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Reference in a new issue