我们有一个Galera DB集群运行3个节点,负载均衡器充当节点之间的中介。我们的应用程序运行多个实例,并且有大量的读/写到数据库,因此我们在使用loadbalancer进行写时遇到了死锁问题。我们通过选择三个特定于写入的节点中的一个来解决这个问题,并且仍然使用负载均衡器进行阅读。
现在,我正在寻找一种解决方案,以便在连接到写节点时遇到问题时设置一个备用连接主机,这样我们就没有停机时间了。我做了很多研究,并在Illuminate\Database\Connectors\ConnectionFactory中发现了这种方法。
/**
* Create a new Closure that resolves to a PDO instance with a specific host or an array of hosts.
*
* @param array $config
* @return \Closure
*/
protected function createPdoResolverWithHosts(array $config)
{
return function () use ($config) {
foreach (Arr::shuffle($hosts = $this->parseHosts($config)) as $key => $host) {
$config['host'] = $host;
try {
return $this->createConnector($config)->connect($config);
} catch (PDOException $e) {
continue;
}
}
throw $e;
};
}我可以为写配置提供多个主机,但Laravel将随机决定使用哪个主机。
'write' => [
'host' => [ "node1", "node2" ],
],我只想始终使用1个节点进行写操作,如果连接出现问题,我希望返回到另一个节点(第二个节点)。有人知道我是怎么做到的吗?看来我不能覆盖createPdoResolverWithHosts的行为,因为它不是服务提供者,而是在Laravel的核心中编码的。
发布于 2022-01-04 18:52:22
因此,查看Illuminate\Database\Connectors\ConnectionFactory类,您的问题包括createPdoResolverWithHosts()方法;当配置中存在hosts键时,您可以看到这是由createPdoResolver()调用的。但是,如果缺少数组键,则调用createPdoResolverWithoutHosts(),直接调用createConnector()方法。该方法返回适当数据库连接器类的实例。但是,在这样做之前,它会检查是否有任何绑定连接器:
if ($this->container->bound($key = "db.connector.{$config['driver']}")) {
return $this->container->make($key);
}因此(请注意,这是完全未经测试的),我建议如下:
创建自定义数据库连接器,扩展默认数据库连接器。将一些自定义逻辑放入connect()方法中,该方法将配置数组作为其唯一参数:
<?php
namespace App\Database;
use Illuminate\Database\Connectors\MySqlConnector as BaseConnector;
class MySqlConnector extends BaseConnector
{
public function connect(array $config)
{
$primary = $config["primary_host"];
$secondary = $config["secondary_host"];
try {
$config["host"] = $primary;
return parent::connect($config);
} catch (\Throwable $e) {
$config["host"] = $secondary;
return parent::connect($config);
}
}
}创建一个服务提供程序来绑定您的自定义DB连接器:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class CustomMysqlConnector extends ServiceProvider
{
public function register()
{
$this->app->bind('db.connector.mysql', \App\Database\MySqlConnector::class);
}
}在应用程序配置中注册提供程序。
<?php
return [
...
'providers' => [
...
App\Providers\CustomMysqlConnector::class,
],
];在配置数组中取消设置host键。相反,使用自定义连接器中使用的primary_host和secondary_host。
https://stackoverflow.com/questions/70581228
复制相似问题