Войти Регистрация
Конкурентность

1. Round-robin балансировщик с health-check

Средняя

Go · 44 строк

Pick вызывается из каждой горутины HTTP-сервера, на пике — 20 тысяч раз в секунду. HealthLoop крутится в одной фоновой горутине и раз в 2 секунды пингует 12 бэкендов.

Отметьте строки с ошибками.

В работе: Внутренний L7-прокси перед пулом бэкендов сервиса.

Как проверяем Нажмите на строку с ошибкой и коротко напишите, что не так. Баг засчитан, если отмечена хотя бы одна его строка. Зачёт — найдено не меньше 60 % багов с учётом серьёзности (критичный весит 3, обычный 2, мелкий 1), а лишних отметок не больше, чем багов в коде. Пустые строки, скобки и комментарии лишними не считаем. Плюс 1 вопрос про поведение программы — на зачёт не влияют. Ответ один на подход: после него показываем разбор.
atomicRWMutexгонка данныхутечка соединений

Источник: обзор транскриптов интервью: Яндекс, балансировщик на Go. Условие пересказано своими словами.

Давали на собеседовании? Ответов пока мало — ваш поможет.
  1. package balancer
  2. import (
  3. "errors"
  4. "net/http"
  5. "sync"
  6. "time"
  7. )
  8. type Balancer struct {
  9. mu sync.RWMutex
  10. backends []string
  11. alive []string
  12. next int
  13. }
  14. func New(backends []string) *Balancer {
  15. return &Balancer{backends: backends, alive: backends}
  16. }
  17. // Pick вызывается из тысяч горутин HTTP-сервера.
  18. func (b *Balancer) Pick() (string, error) {
  19. if len(b.alive) == 0 {
  20. return "", errors.New("no alive backends")
  21. }
  22. b.next++
  23. return b.alive[b.next%len(b.alive)], nil
  24. }
  25. // HealthLoop раз в 2 секунды обновляет список живых бэкендов.
  26. func (b *Balancer) HealthLoop(client *http.Client) {
  27. for range time.Tick(2 * time.Second) {
  28. var alive []string
  29. for _, addr := range b.backends {
  30. resp, err := client.Get("http://" + addr + "/ping")
  31. if err == nil && resp.StatusCode == http.StatusOK {
  32. alive = append(alive, addr)
  33. }
  34. }
  35. b.mu.Lock()
  36. b.alive = alive
  37. b.mu.Unlock()
  38. }
  39. }