Middle
10
type Balancer struct { // TODO backends []*BackendImpl index int mu sync.Mutex N int K time.Duration } var _ Backend = &Balancer{} func (b *Balancer) Invoke(ctx context.Context, req Request) (Response, error) { if len(b.backends) == 0 { return nil, fmt.Errorf("Кол-во backends в слайсе 0") } b.mu.Lock() index := b.index for b.backends[index].banned { b.index = (b.index + 1) % len(b.backends) index = b.index } b.index = (b.index + 1) % len(b.backends) b.mu.Unlock() backend := b.backends[index] resp, err := backend.Backend.Invoke(ctx, req) if err != nil && backend.countErrors < b.N { backend.mu.Lock() backend.countErrors += 1 if backend.countErrors == b.N { backend.banned = true go func() { time.Sleep(b.K) backend.mu.Lock() defer backend.mu.Unlock() backend.banned = false backend.countErrors = 0 }() } backend.mu.Unlock() } return resp, err } // addrs содержат адреса всех балансируемых экземпляров func NewBalancer(addrs []string) *Balancer { // TODO backends := make([]*BackendImplF, len(addrs)) for _, addr := range addrs { implF := BackendImplF{ Backend: NewBackend(addr), } backends = append(backends, &implF) } }
Компании, где спрашивали
Яндекс
Ответ от нейросети
sobes.tech AI
В представленном коде есть несколько проблем:
- В функции
NewBalancerсоздаётся слайсbackendsдлинойlen(addrs), но затем в цикле происходит добавление элементов черезappend, что приводит к тому, что в слайсе сначала идутlen(addrs)нулевых элементов, а потом добавляются новые. В итоге длина слайса будет больше, чем нужно, и первые элементы будутnil.
Правильнее инициализировать слайс с нулевой длиной, но с нужной вместимостью:
backends := make([]*BackendImplF, 0, len(addrs))
- В цикле нужно использовать индекс или правильно добавлять элементы:
for _, addr := range addrs {
implF := BackendImplF{
Backend: NewBackend(addr),
}
backends = append(backends, &implF)
}
-
В структуре
Balancerполеbackendsобъявлено как[]*BackendImpl, а в функции создаются объекты типаBackendImplF. Нужно убедиться, что типы совпадают илиBackendImplFреализует интерфейсBackend. -
В методе
Invokeиспользуется блокировка мьютекса для изменения индекса и выбора backend, что правильно для потокобезопасности. -
Логика банов backend при превышении количества ошибок и снятия бана через горутину с таймером реализована корректно.
Итог: исправьте инициализацию слайса в NewBalancer, чтобы избежать nil элементов и неправильной длины, и проверьте соответствие типов.