В нашей компании мы создаем новостные порталы для довольно большого количества локальных газет (в настоящее время 13, 30 в следующем месяце и более в будущем), каждый из которых отображает 2 тыс. страниц на 100 тыс. страниц в день. Поскольку мы эволюционируем из ситуации, когда каждый сайт сильно настраивается на тот, где каждая разница зависит от конфигурации или пользовательского шаблона, наше программное обеспечение уже почти одинаково для всех сайтов. В настоящее время наша стратегия развертывания - это один экземпляр пушки для каждого сайта (с 1-17 работниками каждый, в зависимости от трафика сайта), на 16-ядерном сервере и 12 ГБ оперативной памяти. Проблема с этой установкой заключается в том, что каждый рабочий (обычный pre-forked gunicorn) принимает 110 МБ, независимо от того, используется ли он или нет. Теперь с новыми сайтами нам нужно будет добавить больше ОЗУ для обслуживания не так много запросов, поэтому в основном он не масштабируется. Кроме того, поскольку мы переходим от этой модели, где каждый сайт независим, каждый сайт имеет свою собственную базу данных, и мне это очень нравится, тем более что мы используем реляционные базы данных (mysql, но переходим к pgsql), поэтому гораздо проще осколочно.
Я занимаюсь некоторыми исследованиями и экспериментирует с запуском всех сайтов на одном экземпляре для пушек, поэтому я мог полностью использовать серверы и добавлять дополнительные серверы за балансировщик нагрузки, когда он пришел к нему. Проблема в том, что django предполагает во многих местах, что на один процесс запускается только один сайт, поэтому, по моему мнению, до сих пор мне пришлось бы реализовать:
- Среднее ПО, которое принимает HTTP_HOST из запроса и помещает идентификатор в переменную threadlocal.
- Загрузчик шаблонов, который использует эту переменную для загрузки настраиваемых шаблонов.
- Monkey patch django.db.model.Model, возможно, добавив метакласс (даже не уверенный, что это возможно, но я думаю, что мне это понадобится из-за привычных менеджеров, которые мы иногда должны использовать), которые перезаписывали бы менеджеров для одного, сначала вызовет db_manager (идентификатор) в исходном менеджере, а затем вызовет предполагаемый метод. Мне также нужно будет перезаписать методы сохранения и удаления, чтобы всегда включать параметр use = identifier.
- Думаю, мне нужно было бы прекратить использование конструкторов include_tag, а не большую проблему, но мне нужно подумать о других случаях, подобных этому.
- Тяжелое и уродливое исправление urlresolvers, если мне нужны пользовательские или дополнительные URL-адреса для каждого сайта. Я не нуждаюсь в них сейчас, но, вероятно, в какой-то момент.
И это именно то, что я придумал, даже не выполнив его и не увидев, где он сломается, я уверен, что мне понадобится еще много изменений для его работы. Поэтому я действительно не хочу этого делать, особенно с дополнительными усилиями по обслуживанию, которые мне понадобятся, но я не вижу альтернатив и мне бы хотелось узнать, что кто-то уже решил это лучше. Конечно, я мог бы вообще полностью отказаться от использования django (у меня уже есть много причин для этого), но это означало бы серьезную переписку и наличие двух поддерживающих две несовместимые ветки программного обеспечения до тех пор, пока новый не достигнет паритета характеристик с версией django, поэтому мне кажется еще хуже, чем все уродливые хаки.