Add HighestRandomWeight Loadbalancing Algorithm
This commit is contained in:
parent
9b42b5b930
commit
02443545e7
10 changed files with 936 additions and 112 deletions
|
|
@ -28,6 +28,7 @@ import (
|
|||
"github.com/traefik/traefik/v3/pkg/server/middleware"
|
||||
"github.com/traefik/traefik/v3/pkg/server/provider"
|
||||
"github.com/traefik/traefik/v3/pkg/server/service/loadbalancer/failover"
|
||||
"github.com/traefik/traefik/v3/pkg/server/service/loadbalancer/hrw"
|
||||
"github.com/traefik/traefik/v3/pkg/server/service/loadbalancer/mirror"
|
||||
"github.com/traefik/traefik/v3/pkg/server/service/loadbalancer/p2c"
|
||||
"github.com/traefik/traefik/v3/pkg/server/service/loadbalancer/wrr"
|
||||
|
|
@ -137,6 +138,13 @@ func (m *Manager) BuildHTTP(rootCtx context.Context, serviceName string) (http.H
|
|||
conf.AddError(err, true)
|
||||
return nil, err
|
||||
}
|
||||
case conf.HighestRandomWeight != nil:
|
||||
var err error
|
||||
lb, err = m.getHRWServiceHandler(ctx, serviceName, conf.HighestRandomWeight)
|
||||
if err != nil {
|
||||
conf.AddError(err, true)
|
||||
return nil, err
|
||||
}
|
||||
case conf.Mirroring != nil:
|
||||
var err error
|
||||
lb, err = m.getMirrorServiceHandler(ctx, conf.Mirroring)
|
||||
|
|
@ -305,6 +313,40 @@ func (m *Manager) getServiceHandler(ctx context.Context, service dynamic.WRRServ
|
|||
}
|
||||
}
|
||||
|
||||
func (m *Manager) getHRWServiceHandler(ctx context.Context, serviceName string, config *dynamic.HighestRandomWeight) (http.Handler, error) {
|
||||
// TODO Handle accesslog and metrics with multiple service name
|
||||
balancer := hrw.New(config.HealthCheck != nil)
|
||||
for _, service := range shuffle(config.Services, m.rand) {
|
||||
serviceHandler, err := m.BuildHTTP(ctx, service.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
balancer.Add(service.Name, serviceHandler, service.Weight, false)
|
||||
|
||||
if config.HealthCheck == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
childName := service.Name
|
||||
updater, ok := serviceHandler.(healthcheck.StatusUpdater)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("child service %v of %v not a healthcheck.StatusUpdater (%T)", childName, serviceName, serviceHandler)
|
||||
}
|
||||
|
||||
if err := updater.RegisterStatusUpdater(func(up bool) {
|
||||
balancer.SetStatus(ctx, childName, up)
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("cannot register %v as updater for %v: %w", childName, serviceName, err)
|
||||
}
|
||||
|
||||
log.Ctx(ctx).Debug().Str("parent", serviceName).Str("child", childName).
|
||||
Msg("Child service will update parent on status change")
|
||||
}
|
||||
|
||||
return balancer, nil
|
||||
}
|
||||
|
||||
type serverBalancer interface {
|
||||
http.Handler
|
||||
healthcheck.StatusSetter
|
||||
|
|
@ -346,6 +388,8 @@ func (m *Manager) getLoadBalancerServiceHandler(ctx context.Context, serviceName
|
|||
lb = wrr.New(service.Sticky, service.HealthCheck != nil)
|
||||
case dynamic.BalancerStrategyP2C:
|
||||
lb = p2c.New(service.Sticky, service.HealthCheck != nil)
|
||||
case dynamic.BalancerStrategyHRW:
|
||||
lb = hrw.New(service.HealthCheck != nil)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported load-balancer strategy %q", service.Strategy)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue