← Назад к вопросам

Что такое балансировка Round Robin?

1.7 Middle🔥 191 комментариев
#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Балансировка Round Robin

Round Robin (RR) — это алгоритм балансировки нагрузки, при котором запросы распределяются поочерёдно (по кругу) между доступными серверами. Это один из самых простых и часто используемых алгоритмов.

Как работает Round Robin

Принцип: каждый новый запрос отправляется на следующий сервер в списке, а после последнего сервера начинаем сначала.

Серверы: [Server1, Server2, Server3]

Запрос 1 → Server1
Запрос 2 → Server2
Запрос 3 → Server3
Запрос 4 → Server1 (вернулись на начало)
Запрос 5 → Server2
Запрос 6 → Server3
Запрос 7 → Server1
...

Простая реализация на Java

public class RoundRobinLoadBalancer {
    private List<String> servers; // Список серверов
    private int currentIndex = 0;  // Текущий индекс
    private final Object lock = new Object(); // Для потокобезопасности
    
    public RoundRobinLoadBalancer(List<String> servers) {
        this.servers = new ArrayList<>(servers);
    }
    
    // Получить следующий сервер
    public String getNextServer() {
        synchronized (lock) {
            String server = servers.get(currentIndex);
            currentIndex = (currentIndex + 1) % servers.size();
            return server;
        }
    }
    
    public static void main(String[] args) {
        List<String> servers = Arrays.asList(
            "192.168.1.1:8080",
            "192.168.1.2:8080",
            "192.168.1.3:8080"
        );
        
        RoundRobinLoadBalancer balancer = new RoundRobinLoadBalancer(servers);
        
        // Имитируем 10 запросов
        for (int i = 1; i <= 10; i++) {
            String server = balancer.getNextServer();
            System.out.println("Запрос " + i + " → " + server);
        }
    }
}

// Вывод:
// Запрос 1 → 192.168.1.1:8080
// Запрос 2 → 192.168.1.2:8080
// Запрос 3 → 192.168.1.3:8080
// Запрос 4 → 192.168.1.1:8080
// Запрос 5 → 192.168.1.2:8080
// Запрос 6 → 192.168.1.3:8080
// Запрос 7 → 192.168.1.1:8080
// Запрос 8 → 192.168.1.2:8080
// Запрос 9 → 192.168.1.3:8080
// Запрос 10 → 192.168.1.1:8080

Варианты Round Robin

1. Weighted Round Robin (взвешенный)

Когда серверы имеют разную мощность, используется вес:

public class WeightedRoundRobinBalancer {
    static class ServerWithWeight {
        String server;
        int weight;
        int currentWeight;
        
        public ServerWithWeight(String server, int weight) {
            this.server = server;
            this.weight = weight;
            this.currentWeight = weight;
        }
    }
    
    private List<ServerWithWeight> servers;
    private int totalWeight;
    
    public WeightedRoundRobinBalancer(List<ServerWithWeight> servers) {
        this.servers = servers;
        this.totalWeight = servers.stream()
            .mapToInt(s -> s.weight)
            .sum();
    }
    
    public String getNextServer() {
        ServerWithWeight selected = null;
        
        // Увеличиваем currentWeight каждого сервера на его вес
        for (ServerWithWeight s : servers) {
            s.currentWeight += s.weight;
            if (selected == null || s.currentWeight > selected.currentWeight) {
                selected = s;
            }
        }
        
        // Уменьшаем currentWeight выбранного сервера на общий вес
        selected.currentWeight -= totalWeight;
        return selected.server;
    }
    
    public static void main(String[] args) {
        List<ServerWithWeight> servers = Arrays.asList(
            new ServerWithWeight("Server1", 5),  // Мощный
            new ServerWithWeight("Server2", 3),  // Средний
            new ServerWithWeight("Server3", 2)   // Слабый
        );
        
        WeightedRoundRobinBalancer balancer = 
            new WeightedRoundRobinBalancer(servers);
        
        System.out.println("Распределение запросов:");
        for (int i = 1; i <= 10; i++) {
            System.out.println("Запрос " + i + " → " + balancer.getNextServer());
        }
    }
}

// Вывод примерно такой:
// Server1 получит ~50% запросов
// Server2 получит ~30% запросов
// Server3 получит ~20% запросов

Плюсы Round Robin

Простота реализации — минимум логики ✅ Предсказуемость — детерминированное распределение ✅ Равномерное распределение — все серверы получают одинаковое количество запросов ✅ Низкая вычислительная сложность — O(1) операция ✅ Хорошо для статичного трафика — когда запросы примерно одинакового размера

Минусы Round Robin

Не учитывает нагрузку — если Server1 перегружен, он всё равно получит запрос ❌ Не учитывает время отклика — слабый сервер может быть медленнее ❌ Sticky sessions — при наличии сессий может быть неудобно ❌ Для разнородных серверов — нужен взвешенный вариант

Когда использовать Round Robin

Подходит:

  • Веб-серверы одинаковой мощности
  • Stateless приложения
  • API endpoints
  • Микросервисы

Не подходит:

  • Когда запросы сильно отличаются по времени обработки
  • Когда серверы имеют разную мощность (нужен Weighted RR)
  • Когда нужны sticky sessions

Сравнение с другими алгоритмами

АлгоритмПреимуществоНедостаток
Round RobinПросто, равномерноНе учитывает нагрузку
Least ConnectionsУчитывает активные соединенияСложнее
IP HashSticky sessionsМожет быть неравномерно
Least Response TimeУчитывает скоростьТребует мониторинга
RandomСлучайныйНепредсказуемо

Пример в контексте микросервисов

// REST Client с Round Robin балансировкой
public class LoadBalancedClient {
    private RestTemplate restTemplate;
    private RoundRobinLoadBalancer balancer;
    
    public LoadBalancedClient(List<String> serverUrls) {
        this.restTemplate = new RestTemplate();
        this.balancer = new RoundRobinLoadBalancer(serverUrls);
    }
    
    public ResponseEntity<String> getFromServer(String endpoint) {
        String server = balancer.getNextServer();
        String url = server + "/api/v1/" + endpoint;
        
        try {
            return restTemplate.getForEntity(url, String.class);
        } catch (Exception e) {
            // Логируем ошибку и можем добавить retry логику
            System.out.println("Ошибка на сервере: " + server);
            throw e;
        }
    }
}

Real-world использование

Nginx конфигурация (самый распространённый вариант):

upstream backend {
    server 192.168.1.1:8080;  # Server 1
    server 192.168.1.2:8080;  # Server 2
    server 192.168.1.3:8080;  # Server 3
    # По умолчанию используется Round Robin
}

server {
    location / {
        proxy_pass http://backend;
    }
}

Spring Cloud LoadBalancer:

@Configuration
public class LoadBalancerConfig {
    @Bean
    public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
            ConfigurableApplicationContext context) {
        // Spring Cloud LoadBalancer также использует Round Robin по умолчанию
        return ServiceInstanceListSupplier.builder()
            .withDiscoveryClient()
            .withHealthChecks()
            .build(context);
    }
}

Итог

Round Robin — это фундаментальный алгоритм балансировки нагрузки, который распределяет запросы поочерёдно между серверами. Он идеален для простых случаев, когда все серверы примерно одинаковой мощности и запросы примерно одинакового размера. Для более сложных сценариев используют взвешенные варианты или более умные алгоритмы, учитывающие текущую нагрузку на серверы.

Что такое балансировка Round Robin? | PrepBro