Как выполнить максимально справедливую балансировку нагрузки на основе конкретных путей к ресурсам - PullRequest
0 голосов
/ 16 августа 2011

У меня есть приложение, которое обслуживает артефакты из файлов (страницы из файлов PDF в виде изображений), оригинальные файлы PDF живут на S3 и загружаются на серверы, которые генерируют изображения, когда клиент нажимает на один из них. Эти машины имеют локальный механизм кэширования, который гарантирует, что каждый файл PDF загружается только один раз.

Итак, когда клиент приходит с запросом , дайте мне страницу 1 из pdf 123.pdf этот кеш проверяется, если там нет файла pdf, он загружается с S3 и сохраняется в локальной кеш, а затем процесс генерирует эту страницу 1 и отправляет изображение обратно клиенту.

Клиент сам не знает, что он подключен к специальному серверу, все выглядит так, как будто он просто обращается к серверу веб-сайта, но ради производительности я хотел бы убедиться, что этот клиент всегда будет направлен на тот же файловый сервер, который обработал свой первый запрос (и загрузил файл с S3).

Я мог бы просто установить cookie на клиенте, чтобы он всегда загружал с этого конкретного файлового сервера, но размещение его на клиенте ведет к несправедливому использованию, поскольку некоторые пользователи собираются открывать много документов, а некоторые нет, хотел бы выполнить балансировку нагрузки на уровне ресурсов (документ PDF).

Каждый документ имеет уникальный идентификатор (целочисленный первичный ключ в базе данных), и моим первым решением было использование Redis и сохранение идентификатора документа в качестве ключа, а значение - это хост сервера, на котором в данный момент этот документ кэширован, но Я хотел бы удалить Redis или искать более простой способ реализации этого, который не требовал бы поиска ключей где-либо еще.

Кроме того, было бы неплохо, если бы определенный алгоритм или идея позволили добавлять больше файловых серверов на лету.

Каков наилучший способ для балансировки нагрузки такого типа с привязкой к ресурсам?

Просто ради того, чтобы сказать, это приложение представляет собой смесь Ruby, Java и Scala.

1 Ответ

2 голосов
/ 16 августа 2011

Я бы использовал следующий подход в балансировщике нагрузки:

  • Удалите запрошенный URL ресурса, чтобы удалить части запроса и фрагмента.
  • Превратите раздетый URL в строкуи возьмите его хеш-код.
  • Используйте хеш-код, чтобы выбрать внутренний сервер из списка доступных серверов;например,

    String[] serverNames = ...
    String serverName = serverNames[hash % serverNames.length];
    

Это равномерно распределяет нагрузку по всем серверам и всегда отправляет один и тот же запрос на один и тот же сервер.Если вы добавляете больше серверов, он настраивается сам ... хотя вы получаете удар по производительности, когда кеширование снова нагревается.

Не думаю, что вы хотите стремиться к "честности";т.е. какая-то гарантия, что каждый запрос занимает примерно одинаковое время.Для достижения справедливости вам необходимо активно отслеживать нагрузку на каждый бэкэнд и распределять ее в соответствии с нагрузкой.Это (в некоторой степени) сведет на нет кэширование / сходство и будет потреблять ресурсы для принятия решений об измерении и распределении нагрузки.Подход с распределением немой нагрузки (например, мое предложение) должен дать вам лучшую пропускную способность в целом для вашего варианта использования.

...