Поддержка нескольких арендаторов в Java EE 6
У меня есть существующее приложение Java EE 6 (развернутое в Glassfish v 3.1) и хочу поддерживать несколько арендаторов. Технологии /API, которые я использую в своем приложении,
- EJB (включая службу таймера EJB)
- JPA 2.0 (EclipseLink)
- JSF 2.0
- JMS
- JAX-RS
- Я также планирую использовать CDI
Насколько я знаю, добавление поддержки с несколькими арендаторами влияет только на уровень сохранения. Мой вопрос: Кто-нибудь сделал это раньше? Каковы шаги для преобразования приложения? Будет ли это влиять на другие уровни, кроме сохранения?
Будет много арендаторов, поэтому все данные будут находиться в одной и той же схеме БД.
Ответы
Ответ 1
Уровень сохранения
Начните с слоя сохранения. Когда вы это сделаете, сверните вверх по своей архитектуре.
Схема, которую вы предлагаете, будет иметь идентификатор, который идентифицирует арендатора (например, TenantId). Каждая таблица будет иметь этот идентификатор. Во всех ваших запросах вам нужно будет убедиться, что TenantId соответствует зарегистрированному пользователю TenantId.
Трудность заключается в том, что это очень ручной процесс.
Если вы перейдете с Hibernate в качестве поставщика JPA, тогда есть некоторые инструменты, которые помогут с этим; а именно Фильтры Hibernate.
Они обычно используются для ограничения доступа к схемам с несколькими арендаторами (см. здесь и здесь для еще нескольких)
Я не использовал EclipseLink, но он выглядит так: имеет хорошую поддержку для Multi-Tenancy. DiscriminatorColumn выглядит как очень похожая концепция для Hibernate Filters.
Уровень обслуживания
Я предполагаю, что вы используете JAX-RS и JMS для уровня обслуживания. Если это так, вам также нужно будет подумать о том, как вы собираетесь передавать tenantId и аутентифицировать своих арендаторов. Как вы собираетесь помешать одному арендатору получить доступ к службе REST другого? То же самое для JMS.
Уровень пользовательского интерфейса
Вам нужно подключить свой логин в своем интерфейсе к Bean (Hibernate или Eclipselink), который устанавливает TenantId для фильтра/дискриминатора.
Ответ 2
Расскажите нам о количестве и степени разделения и настройки, необходимых для разных арендаторов.
Если у вас небольшое количество арендаторов, я бы предложил создать настраиваемый продукт "white-label". Это дает вам возможность создать некоторые конкретные вещи для одного арендатора без чрезмерно сложных вопросов. Кроме того, разделение приложений на одного арендатора помогает вам в обслуживании. Мы сделали это для продукта с несколькими арендаторами.
Если у вас много арендаторов, это, конечно, уже не практично. Мы сделали общую версию того же продукта. Все, что мы делали тогда, заключалось в том, чтобы различать арендаторов по id после входа в систему, тем самым отделяя данные от других. Тем не менее, нечего было делать с точки зрения изменения приложения или уровня внутри, идентификатор был всем необходимым для разделения данных, и рабочий процесс автоматически разделялся наличием разных экземпляров beans или других управляемых объектов.
Ответ 3
Есть несколько способов сделать это, в зависимости от уровня разделения, которого вы хотите достичь, и количества параллельных арендаторов, которые вы хотите поддержать. С одной стороны, вы можете создать новую схему для каждого арендатора и, следовательно, обеспечить изоляцию данных на уровне базы данных. Для большинства практических целей обычно достаточно иметь логическое разбиение ваших данных, назначая tenant_id
каждому объекту в вашей модели домена и поддерживая ограничения внешнего ключа. Конечно, это означает, что вы, вероятно, захотите всегда передавать текущий сеанс tenant_id
каждому методу query/finder, чтобы он мог ограничить набор данных на основе этого. Вы хотите, чтобы пользователи не могли получить доступ к другим данным арендатора, введя идентификатор арендатора (или идентификатор объекта), который не принадлежит им в URL-адресе.
Ответ 4
Перейти к сообщению.
Если вы выбираете обмен сообщениями как стратегический подход и рефакторинг (если необходимо) бизнес-логики вокруг JMS, тогда другие варианты остаются жизнеспособными и применимыми на местах.
При таком подходе вы платите определенную фиксированную стоимость (рефакторинг) в вашей существующей (единой арендованной) системе. Затем вы можете применять подходы различной степени сложности, начиная от простого очертания (ассоциация с основанием @Geziefer id) и заканчивая полномасштабным подходом с общей архитектурой-схемой + расширенным-арендатором, не влияя на архитектуру системы и дополнительный рефакторинг.
Кроме того, вы будете иметь ортогональное управление потоками системных данных через уровень обмена сообщениями (с использованием маршрутизаторов, фильтров, специальных путей обработки и т.д.).
[изменить для запроса]
В М.Т. нет ничего такого. что явно указывает на ориентацию сообщений. Но в качестве общей проблемы мы рассматриваем расширяющиеся интерфейсы и обогащенные потоки данных. Для подхода, основанного на API, вам необходимо тщательно ввести соответствующий дискриминант арендатора во все необходимые интерфейсы (например, методы). Основанное на сообщении (или, альтернативно, подход, основанный на контекстно-зависимом интерфейсе) позволяет использовать нормативный (стабильный) интерфейс (например, message.send()) и в то же время позволяет использовать явные специализированные потоки данных. Если переключение на базовую основу, основанную на сообщениях, отсутствует в таблице, вам настоятельно рекомендуется рассмотреть возможность вставки в ваши API-интерфейсов равномерного контекста (например, "RequestContext" ). Это одно расширение должно охватывать все ваши будущие потребности специализации.