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

Лучшие практики для разработки приложения с несколькими арендаторами с Symfony2 и Doctrine2

Я работаю над приложением, которое должно поддерживать модель с несколькими арендаторами. Я использую рамки symfony2 php и doctrine2.

Я не уверен, что лучший способ сделать это. Является ли функция Symfony ACL частью решения?

Какие рекомендации или идеи вы могли бы предоставить? Есть ли примеры приложений symfony2 или приложений с открытым исходным кодом, которые доступны, которые внедрили эту стратегию?

Моя первая мысль - использовать столбец tenant_id во всех таблицах и связать это с объектом учетной записи в приложении. Я не уверен, хотя если ACL должен заботиться о том, что я хочу делать, или если вы все еще несете ответственность за все запросы против ваших объектов, чтобы они не возвращали неавторизованные данные.

Если бы я не использовал Doctrine, было бы легко сказать просто добавить Where tenant_id = @accountid к каждому запросу, но я не уверен, что это правильный подход.

Спасибо

4b9b3361

Ответ 1

Мы делали это в течение некоторого времени (хотя и не с symfony и доктриной, но проблемы остаются прежними) - мы начали с одной огромной базы данных и реализовали "идентификатор среды" для каждой строки в каждой таблице. Таким образом, миграция схемы была простой: весь код был унифицирован, поэтому изменение схемы было единственным изменением кода и схемы.

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

Затем мы переключились на несколько баз данных; каждая среда имеет свою собственную схему. Используя миграцию, предоставляемую с помощью Doctrine (1 в нашем случае), мы можем быстро обновить все приложение или только одну среду. Также возможность перемещения конкретных изменений между тенентами позволяет повысить точность и скорость.

Моим советом было бы: создать одно ядро, которое будет распространено на разных арендаторов, и сохранить локальную конфигурацию базы данных на каждый тенант. (в структуре, подобной app.ini)

то есть.

/
    apps/
        tentant1/
            models/ <--- specific to the tenant
            libraries/ <--- specific to the tenant
            config/
                app.ini <--- specific configuration
        tentant2/
        /**/ etc
    core/
        models/ <--- system wide models
        libraries/ <--- system wide libraries (i.e. doctrine)
        core.ini <--- system wide configuration

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

Ответ 2

Мы делаем это с одним из наших основных решений на работе, и это, безусловно, возможно. Мы используем пакеты Symfony2 для создания "базового" пакета, который затем расширяется другими пакетами для каждого клиента.

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

Мы также обнаружили, что Doctrine 2 имеет довольно серьезные проблемы, если только он не находится под контролем. Хотя это может быть побочным эффектом плохо структурированного кода и логики базы данных, я чувствую, что это небольшая дыра для ORM, чтобы иметь возможность добраться до точки, где она порождает фатальную ошибку, потому что она использует слишком много памяти, особенно когда только причина, по которой он использует так много памяти, состоит в том, что он дорабатывает SQL-запросы, чтобы их можно было сделать "более эффективными".

Это чисто мое мнение, конечно:) Что не работает для нас, может сработать для вас, но я чувствую, что вам будет лучше хранить отдельные базы данных на клиенте, даже если они все хранятся на том же сервере.

Ответ 3

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

Ответ 4

Почему бы не попробовать разные базы данных для каждого клиента, чтобы сохранить данные в отдельности и предоставить им уникальную точку входа в ваше приложение. Пример: http://client1.project.net, который с системой маршрутизации будет отображаться в базе данных client1. Плохая сторона этого: более сложные изменения базы данных, поскольку все базы данных для каждый клиент нуждается в обновлении.

Ответ 5

Я думаю, что для управления многопользовательской мульти-базой данных с symfony 2/3. Мы можем config auto_mapping: false для ORM доктрины. file: config.yml

doctrine:
    dbal:
        default_connection: master
        connections:
            master:
                driver:   pdo_mysql
                host:     '%master_database_host%'
                port:     '%master_database_port%'
                dbname:   '%master_database_name%'
                user:     '%master_database_user%'
                password: '%master_database_password%'
                charset:  UTF8
            tenant:
                driver:   pdo_mysql
                host:     '%tenant_database_host%'
                port:     '%tenant_database_port%'
                dbname:   '%tenant_database_name%'
                user:     '%tenant_database_user%'
                password: '%tenant_database_password%'
                charset:  UTF8

    orm:
        default_entity_manager: master
        auto_generate_proxy_classes: "%kernel.debug%"
        entity_managers:
            master:
                connection: master
                auto_mapping: false
                mappings:
                    AppBundle:
                        type: yml
                        dir: Resources/master/config/doctrine
            tenant:
                connection: tenant
                auto_mapping: false
                mappings:
                    AppBundle:
                        type: yml
                        dir: Resources/tenant/config/doctrine

После этого мы не сможем обрабатывать соединение каждого арендатора, переопределяя информацию о подключении в request_listener, как и статью: http://mohdhallal.github.io/blog/2014/09/12/handling-multiple-entity-managers-in-doctrine-the-smart-way/ Надеюсь, что эта практика может помочь кому-то, кто работает с мульти-арендатором

Привет,

Вуонг Нгуен

Ответ 6

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

Я просмотрел эту ссылку, которая описывает способ сделать это для простого старого MySQL (не с Symfony/Doctrine).

В принципе, у вас есть фактические таблицы базы данных, но в каждой таблице есть столбец, в котором хранится имя пользователя базы данных, который сделал строку. Затем создаются представления, которые всегда фильтруются в этом столбце, поэтому всякий раз, когда пользователь входит в базу данных (через средство администрирования или даже через Symfony/Doctrine), они всегда возвращают записи, непосредственно связанные с ними. Это позволяет хранить данные "отдельно", но все же в одной базе данных. При извлечении данных (например, для объекта в Symfony) вы извлекаете данные из отфильтрованного представления и фактической таблицы базы данных.

Теперь это решение не совсем дружит с Symfony/Doctrine. Я смог получить очень быстрый и рудиментарный тест этого бега; Doctrine умеет правильно использовать представления базы данных (это может вставлять, редактировать и удалять записи из представления без проблем). Однако, когда вы делаете что-то вроде создания/обновления схемы, это не весело. Конечно, Symfony/Doctrine кажется довольно расширяемым, поэтому я уверен, что есть способ автоматизировать его, но такая настройка не поддерживается из коробки. Доктрине нужно будет обновить таблицы, всегда добавьте столбец для хранения имени пользователя в создаваемые таблицы сущностей, обновите представления и т.д. (Вам также понадобится способ загрузить правильную конфигурацию базы данных в вашем Symfony, в основном разные логины, так как сервер и другие вещи были бы одинаковыми.) Но если это можно преодолеть, ваше приложение может запустить эти многократные арендаторы, полностью "неосведомленные" о том, что данные других людей находятся в базы данных.