Назад | Перейти на главную страницу

Кластеризация серверов (Django, Apache, Nginx, Postgres)

У меня есть проект, развернутый с помощью django, Apache, Nginx и Postgres. В проекте есть требование, чтобы данные были доступны для просмотра клиентам. Основные моменты проекта: 1. Устройства в полевых условиях отправляют данные на сервер (устройства также похожи на пользователей веб-сайтов) после входа в систему. 2. Существует фоновый процесс импорта, который импортирует загруженные данные в postgres. 3. Веб-пользователи системы используют эти данные и могут отправлять команды устройствам, которые устройства считывают при входе в систему. 4. Существуют также процедуры фонового анализа данных.

Все вышеупомянутые настройки и система развернуты на одной облачной машине amazon EC2. В настоящее время проект поддерживает более 600 устройств и 400 пользователей. Но по мере того, как количество устройств увеличивается со временем, производительность сервера падает.

Мы хотим расширить этот проект, чтобы он мог поддерживать все больше и больше устройств. Моя первоначальная мысль: мы создадим еще один сервер, подобный текущему, и разделим устройства между ними на серверы. Но снова нам нужен центральный пользователь и точка управления устройством через администратора django.

Любые идеи? Каковы наилучшие способы создания масштабируемой архитектуры? Как я могу создать кластер Postgres и использовать его с Django, если это возможно?

В вашем вопросе мало деталей и много размахивания руками, но похоже, что ваше первоначальное мышление - довольно хорошее начало. Ваше приложение звучит очень похоже на пакет мониторинга Zenoss, который использует, по сути, ту же архитектуру распределения нагрузки для масштабирования: несколько хостов мониторинга совместно используют рабочую нагрузку по сбору данных, с одним интерфейсом администратора и базой данных либо на хосте администратора, либо на отдельном система.

Если ваше узкое место находится в точке №1 (устройства, отправляющие данные на ваш сервер), разделение этих задач между двумя машинами должно освободить место для роста нагрузки. Самым большим препятствием при реализации обычно является управление задачами на нескольких серверах Django. Celery, распределенный механизм очереди задач, вероятно, лучший вариант на данный момент. Первоначально он был разработан на основе Django, что хорошо для вас, и у него очень активное и полезное сообщество разработчиков и пользователей.

Если точки №2 и №4 являются вашим текущим ограничением, вы, вероятно, говорите о масштабируемости базы данных. В общем, это просто сложная проблема: не существует прозрачного для кода, нейтрального по нагрузке и дешевого способа увеличения емкости базы данных.

Если вам нужно только увеличить пропускную способность ввода-вывода для «чтения» базы данных, репликация, вероятно, сделает свое дело. Postgres поддерживает репликацию с помощью внешнего инструмента Slony-I. Это репликация с одним мастером, с несколькими «подчиненными» хостами, доступными только для чтения, которые получают копии операторов, выполняемых на главном сервере. Все записи вашего приложения (UPDATE, INSERT, DELETE ...) проходят через единственный главный хост, но вы распределяете свои чтения (SELECT ...) между мастером и всеми подчиненными устройствами.

Модификации кода, необходимые для распределенного чтения, обычно довольно просты. Django недавно добавил поддержку реплицированных баз данных, которую я не использовал, но она должна быть довольно хорошей.

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

Кроме того, я хочу упомянуть Memcached, который сегодня, кажется, является частью практически каждого высокомасштабируемого веб-приложения в Интернете (Facebook, Google, Twitter ...). Хорошая реализация кэширования может сократить требования к вашей базе данных до доли от их исходного размера за счет преобразования дорогостоящих медленных поисков в БД в дешевые и быстрые поиски в кэше. Django уже довольно давно поддерживает интеграцию с Memcached.

Я понимаю, что все это не является слишком конкретным, но это должно дать вам неплохую отправную точку для проработки деталей. Удачи с вашим проектом.

Прежде всего, вы должны понять, где ваш ботильон? Проблема прикладного уровня? Доступ к уровню данных? Какая у вас модель доступа? В основном читает? А может в основном пишет?

Для прикладного уровня:

  • добавление дополнительных серверов приложений
  • некоторые действия могут быть помещены в очередь заданий без ожидания завершения пользователем (например, команды устройствам)

Для уровня данных есть несколько способов, которыми вы можете следовать:

  • Подумайте о своей загруженности? Не могли бы вы уменьшить количество запросов? Не могли бы вы изменить свою схему? Возможно добавление денормализации (предварительная статистика, агрегирование данных). Для очень больших таблиц вы, вероятно, могли бы добавить вертикальное разделение
  • Для масштабирования чтения вы можете использовать репликацию, как сказал Райан Б. Линч.
  • Кеширование с помощью memcached или чего-то подобного. Но помните: «В информатике есть только две сложные вещи: недействительность кеша и именование вещей».
  • Я не рекомендую сегментирование (горизонтальное разбиение), потому что управление сегментированной базой данных болезненно. Вот хорошая статья насчет шардинга.
  • Разделите свои данные на разные серверные части. Вот хорошая статья описывая идею.