如何在 CakePHP 中管理读写 AWS Aurora 主机端点?
How do I manage read and write AWS Aurora host endpoints in CakePHP?
我正在使用基于 CakePHP 的 API,它利用 AWS Aurora 来管理我们的 MySQL 数据库。 CakePHP 应用程序有许多大型读取查询,需要单独 Reader Endpoint 才能不耗尽数据库资源。
它的工作方式是当您将 CakePHP 连接到它时,AWS 会为您提供单独的端点以在主机字段中使用。
我继续按照以下方式配置它,这很有效。以下数据源在 config/app.php 中设置,使用主机值的 reader 和群集(默认)端点:
<?php
// Other data-source and app settings are omitted, to keep things simple
return [
'Datasources' => [
'default' => [
'host' => 'mydbcluster.cluster-123456789012.us-east-1.rds.amazonaws.com',
],
'read' => [
'host' => 'mydbcluster.cluster-ro-123456789012.us-east-1.rds.amazonaws.com',
],
]
];
'read' 和 'default' 数据源都指向同一个数据库,但是这个额外的数据源纯粹配置为支持只读主机值。
此时,我要做的就是覆盖默认连接以读取需要读取连接的查询:
<?php
/**
* Class TaskNotesController
*
* @property \App\Model\Table\TaskNotesTable $TaskNotes
*/
class TaskNotesController extends \Cake\Controller\Controller
{
public function index(): void
{
$taskNotes = $this->TaskNotes
->setConnection(\Cake\Datasource\ConnectionManager::get('read'))
->find('all')
->where(['foo' => 'bar']);
}
}
但是,我想将读取端点应用于应用程序中的所有读取查询。似乎 Cake 会有一种更简洁的方法来执行此操作,以避免在每个查询上附加 setConnection() 调用。
你能告诉我在 CakePHP 中是否有更精简的方法来做到这一点?
提前致谢!
这个话题偶尔会出现,但结论总是这不是核心想要支持的东西:https://github.com/cakephp/cakephp/issues/9197
所以你只能靠自己了,有很多方法可以用更 DRY 的方式解决这个问题,但这在很大程度上取决于你的应用程序的特定需求。很难就此给出任何适当的通用建议,因为做错事会带来可怕的后果。
就像您盲目地将特定连接应用于所有读取操作一样,当您的应用程序将在不同的连接上发出读取而您正在写入一些内容时,您很可能最终会非常难过基于读取的数据。
很遗憾,您可以将模型分成 read/write 个,沿着 CQRS-ish 路线,您可以使用为您的表提供更直接和可重用 API 的行为,您可以将您的操作移至模型层并以这种方式隐藏可能有点脏的实现,您可以根据请求的端点配置默认连接,例如它是读取还是写入等。
“解决”问题的方法有很多,但恐怕这里没有人能给出明确的答案。
我也需要这个,并通过将 Table class 扩展为“AppTable”解决了这个问题。我覆盖了 find()
方法以使用不同版本的 query()
,我称之为 readQuery()
。在我的 readQuery()
中,我修改了 $_connection
成员变量以使用我的 read-only 连接 ,然后 使用 $this->query()
生成查询。然后当生成查询时,我将其切换回写入连接。我进行了检查以确保在存在活动事务或请求生命周期中之前已写入任何内容时我没有执行此操作(因为复制可能尚未完成,并且我会得到旧数据)。
设置起来并不难;你只需要愿意扩展 Cake 的基础 Table class 一点,以便在 find() 中生成查询对象时在两个连接之间切换。
我正在使用基于 CakePHP 的 API,它利用 AWS Aurora 来管理我们的 MySQL 数据库。 CakePHP 应用程序有许多大型读取查询,需要单独 Reader Endpoint 才能不耗尽数据库资源。
它的工作方式是当您将 CakePHP 连接到它时,AWS 会为您提供单独的端点以在主机字段中使用。
我继续按照以下方式配置它,这很有效。以下数据源在 config/app.php 中设置,使用主机值的 reader 和群集(默认)端点:
<?php
// Other data-source and app settings are omitted, to keep things simple
return [
'Datasources' => [
'default' => [
'host' => 'mydbcluster.cluster-123456789012.us-east-1.rds.amazonaws.com',
],
'read' => [
'host' => 'mydbcluster.cluster-ro-123456789012.us-east-1.rds.amazonaws.com',
],
]
];
'read' 和 'default' 数据源都指向同一个数据库,但是这个额外的数据源纯粹配置为支持只读主机值。
此时,我要做的就是覆盖默认连接以读取需要读取连接的查询:
<?php
/**
* Class TaskNotesController
*
* @property \App\Model\Table\TaskNotesTable $TaskNotes
*/
class TaskNotesController extends \Cake\Controller\Controller
{
public function index(): void
{
$taskNotes = $this->TaskNotes
->setConnection(\Cake\Datasource\ConnectionManager::get('read'))
->find('all')
->where(['foo' => 'bar']);
}
}
但是,我想将读取端点应用于应用程序中的所有读取查询。似乎 Cake 会有一种更简洁的方法来执行此操作,以避免在每个查询上附加 setConnection() 调用。
你能告诉我在 CakePHP 中是否有更精简的方法来做到这一点?
提前致谢!
这个话题偶尔会出现,但结论总是这不是核心想要支持的东西:https://github.com/cakephp/cakephp/issues/9197
所以你只能靠自己了,有很多方法可以用更 DRY 的方式解决这个问题,但这在很大程度上取决于你的应用程序的特定需求。很难就此给出任何适当的通用建议,因为做错事会带来可怕的后果。
就像您盲目地将特定连接应用于所有读取操作一样,当您的应用程序将在不同的连接上发出读取而您正在写入一些内容时,您很可能最终会非常难过基于读取的数据。
很遗憾,您可以将模型分成 read/write 个,沿着 CQRS-ish 路线,您可以使用为您的表提供更直接和可重用 API 的行为,您可以将您的操作移至模型层并以这种方式隐藏可能有点脏的实现,您可以根据请求的端点配置默认连接,例如它是读取还是写入等。
“解决”问题的方法有很多,但恐怕这里没有人能给出明确的答案。
我也需要这个,并通过将 Table class 扩展为“AppTable”解决了这个问题。我覆盖了 find()
方法以使用不同版本的 query()
,我称之为 readQuery()
。在我的 readQuery()
中,我修改了 $_connection
成员变量以使用我的 read-only 连接 ,然后 使用 $this->query()
生成查询。然后当生成查询时,我将其切换回写入连接。我进行了检查以确保在存在活动事务或请求生命周期中之前已写入任何内容时我没有执行此操作(因为复制可能尚未完成,并且我会得到旧数据)。
设置起来并不难;你只需要愿意扩展 Cake 的基础 Table class 一点,以便在 find() 中生成查询对象时在两个连接之间切换。