Symfony 4、Doctrine 和 AWS RDS 只读副本使用

Mat*_*Dev 3 php doctrine symfony doctrine-orm

我即将开始使用具有主读/写和从只读设置的 RDS。

我已经阅读了 Doctrine MasterSlaveConnection 类型。

但是,我会创建一些我想使用只读副本的端点(我的大多数 GET 端点),有些需要写入数据(PUT、PATCH、DELETE 端点)。

我也在使用 API 平台。

在 Symfony 4 和 Doctrine 2 中实现这一目标的最佳方法是什么?

zed*_*zed 6

实际上,您不需要设置多个实体管理器,也不是更好的选择,因为使用多个实体管理器处理一个实体很困难。

使用 Doctrine 2.2,您可以直接从配置中设置从属/副本,而不需要额外的实体管理器:

请参阅此处的配置参考: https ://www.doctrine-project.org/projects/doctrine-bundle/en/2.2/configuration.html#configuration-overview

例子:

doctrine:
    dbal:
        default_connection: default
        connections:
            default:
                dbname: '%env(DATABASE_DBNAME)%'
                user: '%env(DATABASE_USER)%'
                password: '%env(DATABASE_PASSWORD)%'
                host: '%env(DATABASE_HOST)%'
                driver: 'pdo_mysql'
                server_version: '5.7'
                charset: utf8mb4
                default_table_options:
                    charset: utf8mb4
                    collate: utf8mb4_unicode_ci
                slaves:
                    ro_replica:
                        dbname: '%env(REPLICA_DBNAME)%'
                        user: '%env(REPLICA_USER)%'
                        password: '%env(REPLICA_PASSWORD)%'
                        host: '%env(REPLICA_HOST)%'
                        charset: utf8mb4
Run Code Online (Sandbox Code Playgroud)


Cha*_*ase 5

我过去所做的只是使用不同的连接。

就像是:

doctrine:
  dbal:
    default_connection: default
    connections:
      default:
        # This is your Master
        url: '%env(DATABASE_URL)%'
        driver: 'pdo_mysql'
        server_version: '5.7'
        charset: utf8mb4
      slave:
        # This would be the slave
        url: '%env(DATABASE_SLAVE_URL)%'
        driver: 'pdo_mysql'
        server_version: '5.7'
        charset: utf8mb4

  orm:
    default_entity_manager: default
    entity_managers:
      default:
        connection: default
        mappings:
          Main:
            is_bundle: false
            type: annotation
            dir: '%kernel.project_dir%/src/Entity'
            prefix: 'App\Entity'
            alias: Main
      slave:
        connection: slave
        mappings:
          Main:
            is_bundle: false
            type: annotation
            dir: '%kernel.project_dir%/src/Entity'
            prefix: 'App\Entity'
            alias: Main
Run Code Online (Sandbox Code Playgroud)

https://symfony.com/doc/current/doctrine/multiple_entity_managers.html

然后在您的控制器或业务逻辑中,您可以选择使用默认实体管理器:

// Controller
$this->getDoctrine()->getEntityManager();
Run Code Online (Sandbox Code Playgroud)

或者您可以获得从属连接:

// Controller
$this->getDoctrine()->getEntityManager('slave');
Run Code Online (Sandbox Code Playgroud)

如果您需要它只处理所有请求,而不必为所有内容创建特殊操作,那么您最好的选择是为学说装饰 Collection 和 Item DataProvider。

https://symfony.com/doc/current/service_container/service_decoration.html

https://github.com/api-platform/core/blob/master/src/Bridge/Doctrine/Orm/CollectionDataProvider.php

https://github.com/api-platform/core/blob/master/src/Bridge/Doctrine/Orm/ItemDataProvider.php

所以基本上你需要根据以下内容更改选择的经理$opperationName

if($opperationName === 'GET'){
    $manager = $this->managerRegistry->getManager('slave');
} else {
    $manager = $this->managerRegistry->getManager();
}
Run Code Online (Sandbox Code Playgroud)