Запуск нескольких сайтов на одном процессе Python

В нашей компании мы создаем новостные порталы для довольно большого количества местных газет (в настоящее время 13, в следующем месяце будет 30 и больше в будущем), каждая из которых имеет от 2 до 100 тысяч просмотров страниц в день. Поскольку мы эволюционируем от ситуации, когда каждый сайт был сильно настроен на один, где каждое различие зависит от конфигурации или настраиваемого шаблона, наше программное обеспечение уже практически одинаково для всех сайтов. Прямо сейчас наша стратегия развертывания - это один экземпляр Gunicorn для каждого сайта (с 1-17 рабочими на каждом, в зависимости от трафика сайта), на 16-ядерном сервере и 12 ГБ ОЗУ. Проблема с этой настройкой заключается в том, что каждый воркер (обычный предварительно разветвленный Gunicorn) занимает 110 МБ, независимо от того, используется он или нет. Теперь с новыми сайтами нам нужно будет добавить больше ОЗУ, чтобы обслуживать не так много запросов, поэтому в основном он не масштабируется. Кроме того, поскольку мы переходим от этой модели, где каждый сайт является независимым, каждый сайт имеет свою собственную базу данных, и мне это очень нравится, тем более что мы используем реляционные базы данных (mysql, но переход на pgsql), поэтому его намного проще

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

  • Промежуточное ПО, которое принимает HTTP_HOST из запроса и помещает идентификатор в переменную threadlocal.
  • Загрузчик шаблонов, который использует эту переменную для соответствующей загрузки пользовательских шаблонов.
  • Monkey patch django.db.model.Model, вероятно, добавляя метакласс (даже не уверен, что это возможно, но я думаю, мне это понадобится из-за настраиваемых менеджеров, которые нам иногда нужно использовать), которые перезаписывают менеджеры для одного, который сначала вызовет db_manager (идентификатор) в исходном менеджере, а затем вызовет предполагаемый метод. Мне также нужно было бы перезаписать методы сохранения и удаления, чтобы всегда включать параметр using = identifier.
  • Думаю, мне нужно было бы прекратить использование декораторов include_tag, это не большая проблема, но мне нужно подумать о других подобных случаях.
  • Тяжелая и уродливая установка исправлений для URL-адресов, если мне нужны специальные или дополнительные URL-адреса для каждого сайта. Сейчас они мне не нужны, но, вероятно, в какой-то момент они мне понадобятся.

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

14
задан Luiz Geron 24 June 2011 в 18:57
поделиться