Подтвердить что ты не робот

Оптимальная архитектура для многопользовательского приложения на django

Я размышлял над правильным/оптимальным способом создания приложения на основе многоуровневых приложений на Django.

Некоторое объяснение:

  • Приложение может использоваться несколькими арендаторами (tenant1, tenant2,...,).

  • Все индивидуальные данные арендатора должны быть защищены от доступа других арендаторов (и их пользователей).

  • При желании арендаторы могут создавать дополнительные пользовательские поля для объектов-приложений.

  • Конечно, базовое оборудование ограничивает количество арендаторов на одной "системе".

1) Разделение каждого арендатора, например. поддомена и использования баз данных, специфичных для арендаторов, в нижележащем слое

2) Использование некоторого идентификатора арендатора в модели для разделения данных арендатора в базе данных

Я думаю о процессах развертывания, производительности системных частей (веб-сервер (ы), сервер базы данных, рабочие node (s),...)

Какая была бы лучшая настройка? Где про и кон?

Как вы думаете?

4b9b3361

Ответ 1

Мы построили платформу с использованием следующей архитектуры. Надеюсь, вы найдете полезные подсказки.

  • Каждый арендатор получает субдомен (t1.example.com)
  • Использование url-переписывания запросов для приложения Django переписывается на что-то вроде example.com/t1
  • Все определения url имеют префикс с чем-то вроде (r'^(?P<tenant_id>[\w\-]+)
  • A middleware обрабатывает и потребляет tenant_id и добавляет его в запрос (например, request.tenant = 't1')
  • Теперь у вас есть текущий арендатор, доступный в каждом представлении без указания аргумента tenant_id для каждого представления
  • В некоторых случаях у вас нет запроса. Я решил эту проблему, привязывая tenant_id к текущему потоку (аналогично текущему языку, используя threading.local)
  • Создайте декораторы (например, осведомленные арендаторы login_required), посредники или фабрики для защиты представлений и выбора правильных моделей.
  • Что касается баз данных, я использовал два разных сценария:
    • Настройка нескольких баз данных и настройка routing в соответствии с текущим арендатором. Я использовал это сначала, но через один год переключился на одну базу данных. Причины были следующие:
      • Нам не нужно высокое безопасное решение для разделения данных
      • Различные арендаторы использовали практически все те же модели
      • Нам пришлось управлять множеством баз данных (и не создавал простой процесс обновления/переноса)
    • Используйте одну базу данных с некоторыми простыми таблицами сопоставления для пользователей и разных моделей. Чтобы добавить дополнительные и специализированные поля модели, мы используем наследование модели.

Что касается среды, мы используем следующую настройку:

С моей точки зрения, эта настройка имеет следующие pro и con:

Pro:

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

Contra:

  • Одна довольно большая база данных
  • Некоторые очень похожие таблицы из-за наследования модели
  • Не защищен на уровне базы данных

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

Обновление. Когда мы рассмотрели нашу архитектуру, я предлагаю не переписывать URL-адрес, как указано в пункте 2-3. Я считаю, что лучшим решением является размещение tenant_id в качестве заголовка запроса и извлечение (точка 4) tenant_id из запроса с чем-то вроде request.META.get('TENANT_ID', None). Таким образом, вы получаете нейтральные URL-адреса, и гораздо проще использовать встроенные функции Django (например, {% url ...%} или reverse()) или внешние приложения.

Ответ 2

Вот несколько указателей на связанные обсуждения:

Ответ 3

Я рекомендую взглянуть на https://github.com/bcarneiro/django-tenant-schemas. Он будет решать ваши проблемы немного как упоминалось в Reto, за исключением того, что он использует схемы postgresql.