
type Response interface{}
type Backend interface {
Invoke(ctx context.Context, req Request) (Response, error)
}
var _ Backend = &BackendImpl{}
// addr contiene ip:port di una istanza specifica
func NewBackend(addr string) *BackendImpl
type backentry struct {
backend Backend
inflight int64
}
type Balancer struct {
backends []*backentry
mu *sync.Mutex
}
var _ Backend = &Balancer{}
// addrs contiene gli indirizzi di tutte le istanze bilanciate
func NewBalancer(addrs []string) *Balancer {
data := make([]*backentry,len(addrs))
for i,addr := range addrs{
data[i] = &backentry{
backend: NewBackend(addr),
inflight: 0,
}
}
return &Balancer{backends:data}
}
func(b *Balancer)Invoke(ctx context.Context, req Request) (Response, error){
b.mu.Lock()
entry := b.best()
atomic.AddInt64(&entry.inflight,1)
b.mu.Unlock()
defer atomic.AddInt64(&entry.inflight,-1)
return entry.backend.Invoke(ctx,req)
}
func(b *Balancer) best() *backentry{
var best *backentry
for _,entry := b.backends{
if best == nil || atomic.LoadInt64(&entry.inflight) < atomic.LoadInt64(&best.inflight){
best = entry
}
}
return best
}