Middle
tüüp Response liides {} tüüp Backend liides { Invoke(ctx: kontekst, req: Request): Response, error } var _ Backend = &BackendImpl{} // addr näitab konkreetse näite ip:port aadressi func NewBackend(addr: string) *BackendImpl tüüp Balancer struktuur { // TODO backends []*BackendImpl index int mu sync.Mutex } var _ Backend = &Balancer{} func (b: *Balancer) Invoke(ctx: kontekst, req: Request) (Response, error) { kui len(b.backends) == 0 { tagasta nil, fmt.Errorf("Backends massiivis on 0 elementi") } b.mu.Lock() index := b.index kui b.index + 1 == len(b.backends) { b.index = 0 index = 0 } b.mu.Unlock() resp, err := b.backends[index].Invoke(ctx, req) tagasta resp, err } // addrs sisaldab kõiki tasakaalustatud näidete aadresse func NewBalancer(addrs: []string) *Balancer { // TODO backends := make([]*BackendImpl, len(addrs))
sobes.tech AI
Vastus AI-lt
В представленном коде балансировщик (Balancer) реализует интерфейс Backend и распределяет вызовы между несколькими экземплярами BackendImpl по кругу (round-robin).
В методе Invoke есть ошибка в логике обновления индекса:
b.mu.Lock()
index := b.index
if b.index + 1 == len(b.backends) {
b.index = 0
index = 0
}
b.mu.Unlock()
Здесь b.index не увеличивается, а только сбрасывается в 0, из-за чего всегда выбирается первый backend.
Правильная реализация должна:
- Зафиксировать текущий индекс
- Увеличить
b.indexс переходом на 0 при достижении конца слайса
Пример исправления:
b.mu.Lock()
index := b.index
b.index = (b.index + 1) % len(b.backends)
b.mu.Unlock()
resp, err := b.backends[index].Invoke(ctx, req)
return resp, err
Также в функции NewBalancer нужно инициализировать слайс backends и заполнить его экземплярами BackendImpl по адресам из addrs:
func NewBalancer(addrs []string) *Balancer {
backends := make([]*BackendImpl, len(addrs))
for i, addr := range addrs {
backends[i] = NewBackend(addr)
}
return &Balancer{
backends: backends,
}
}
Таким образом, балансировщик корректно распределит запросы по backend-экземплярам в круговом порядке.