Какие алгоритмы балансировки нагрузки (load balancing) ты знаешь?

Ответ

Распространённые алгоритмы балансировки нагрузки:

Алгоритм Принцип работы Плюсы Минусы
Round Robin Запросы распределяются по серверам по очереди. Простота реализации. Не учитывает текущую нагрузку серверов.
Weighted Round Robin Как Round Robin, но серверам назначаются веса (более мощные получают больше запросов). Учитывает разную производительность серверов. Не учитывает реальную текущую нагрузку.
Least Connections Новый запрос отправляется на сервер с наименьшим количеством активных соединений. Эффективен при разной длительности запросов. Требует отслеживания состояния соединений.
IP Hash Сервер для клиента определяется хэшем его IP-адреса. Гарантирует, что запросы одного клиента идут на один сервер (полезно для сессий). Может привести к неравномерному распределению.
Least Response Time Запрос отправляется на сервер с наименьшей средней задержкой ответа. Учитывает и нагрузку, и производительность. Сложнее в реализации и требует метрик.

Пример реализации Round Robin на Python:

class RoundRobinBalancer:
    def __init__(self, servers):
        self.servers = servers
        self.current = 0

    def get_next_server(self):
        """Возвращает следующий сервер по круговому алгоритму."""
        server = self.servers[self.current]
        self.current = (self.current + 1) % len(self.servers)
        return server

# Использование
balancer = RoundRobinBalancer(["app-server-1", "app-server-2", "app-server-3"])
for _ in range(5):
    print(balancer.get_next_server())
# Вывод: app-server-1, app-server-2, app-server-3, app-server-1, app-server-2

Ответ 18+ 🔞

А, ну вот, блядь, классика жанра — алгоритмы балансировки нагрузки. Сидишь ты такой, думаешь, как бы эту хуйню по серверам раскидать, чтобы один не сдох, пока другие в ус не дуют. Так, слушай сюда, сейчас разжую.

Смотри, есть у нас несколько популярных способов, прям как инструменты в гараже: молоток, гвоздодёр, дрель с перфоратором. Каждый для своего случая.

Round Robin — это как очередь в столовой, ёпта. Первый запрос — на первый сервер, второй — на второй, и так по кругу. Проще пареной репы, но есть нюанс: а если один сервер уже еле дышит, а другой прохлаждается? А ему всё равно, он тупо по списку идёт. Неадекват, блядь.

Weighted Round Robin — это уже умнее. Ты смотришь, у тебя сервер — монстр с шестнадцатью ядрами, а другой — старенький одноногий хомяк в колесе. Вот первому даёшь вес 5, а второму — 1. И запросы кидаешь соответственно. Но опять же, он не видит, что монстр в данный момент упарывается рендерингом 4К видео, а хомяк просто файлы отдаёт. Не учитывает реальную загрузку, сука.

Least Connections — вот это уже ближе к телу. Он смотрит, у кого меньше всего активных соединений висит, и нового клиента туда суёт. Логично же? Если один сервер уже по уши в работе, а другой почти свободен — ну не иди же к занятому! Но за этой хуйней надо следить, считать эти соединения — лишняя морока.

IP Hash — хитрая жопа. Берёт IP клиента, пропускает через хеш-функцию, и на основе этого числа определяет, на какой сервер его всегда отправлять. Это чтобы сессии не терялись, понимаешь? Клиент залогинился на одном сервере — и все его запросы туда же. Но если у тебя клиентов с одного IP-пула дохуя, может получиться так, что один сервер будет в ахуе, а другие — в пролёте. Неравномерно, блядь.

Least Response Time — это уже высший пилотаж, ёбана. Он не только соединения считает, но и замеряет, кто быстрее отвечает. Отправляет запрос туда, где среднее время ответа меньше всего. Идеально в теории, но на практике — овердохуища метрик нужно собирать и анализировать. Реализовать — ещё та песня.

А вот, смотри, как тупой Round Robin на Python выглядит, чтоб ты понимал масштаб трагедии:

class RoundRobinBalancer:
    def __init__(self, servers):
        self.servers = servers
        self.current = 0

    def get_next_server(self):
        """Возвращает следующий сервер по круговому алгоритму."""
        server = self.servers[self.current]
        self.current = (self.current + 1) % len(self.servers)
        return server

# Использование
balancer = RoundRobinBalancer(["app-server-1", "app-server-2", "app-server-3"])
for _ in range(5):
    print(balancer.get_next_server())
# Вывод: app-server-1, app-server-2, app-server-3, app-server-1, app-server-2

Видишь? Тупо перебирает их по кругу, как барабан револьвера. Ни хуя не знает про нагрузку. Но зато код — три строчки, и работает. Иногда и этого хватает, если серверы одинаковые и запросы лёгкие. А если нет — ну, извини, пиздец наступит незаметно. Выбирай с умом, а то потом разгребать придётся.