首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否有可能将后备数据库写主机配置为laravel,而不是随机选择要使用的连接?

问是否有可能将后备数据库写主机配置为laravel,而不是随机选择要使用的连接?
EN

Stack Overflow用户
提问于 2022-01-04 15:30:15
回答 1查看 274关注 0票数 0

我们有一个Galera DB集群运行3个节点,负载均衡器充当节点之间的中介。我们的应用程序运行多个实例,并且有大量的读/写到数据库,因此我们在使用loadbalancer进行写时遇到了死锁问题。我们通过选择三个特定于写入的节点中的一个来解决这个问题,并且仍然使用负载均衡器进行阅读。

现在,我正在寻找一种解决方案,以便在连接到写节点时遇到问题时设置一个备用连接主机,这样我们就没有停机时间了。我做了很多研究,并在Illuminate\Database\Connectors\ConnectionFactory中发现了这种方法。

代码语言:javascript
复制
/**
 * 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将随机决定使用哪个主机。

代码语言:javascript
复制
'write'     => [
    'host' => [ "node1", "node2" ],
],

我只想始终使用1个节点进行写操作,如果连接出现问题,我希望返回到另一个节点(第二个节点)。有人知道我是怎么做到的吗?看来我不能覆盖createPdoResolverWithHosts的行为,因为它不是服务提供者,而是在Laravel的核心中编码的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-01-04 18:52:22

因此,查看Illuminate\Database\Connectors\ConnectionFactory类,您的问题包括createPdoResolverWithHosts()方法;当配置中存在hosts键时,您可以看到这是由createPdoResolver()调用的。但是,如果缺少数组键,则调用createPdoResolverWithoutHosts(),直接调用createConnector()方法。该方法返回适当数据库连接器类的实例。但是,在这样做之前,它会检查是否有任何绑定连接器:

代码语言:javascript
复制
if ($this->container->bound($key = "db.connector.{$config['driver']}")) {
    return $this->container->make($key);
}

因此(请注意,这是完全未经测试的),我建议如下:

创建自定义数据库连接器,扩展默认数据库连接器。将一些自定义逻辑放入connect()方法中,该方法将配置数组作为其唯一参数:

代码语言:javascript
复制
<?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连接器:

代码语言:javascript
复制
<?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);
    }
}

在应用程序配置中注册提供程序。

代码语言:javascript
复制
<?php

return [
    ...
    'providers' => [
        ...
        App\Providers\CustomMysqlConnector::class,
    ],
];

在配置数组中取消设置host键。相反,使用自定义连接器中使用的primary_host和secondary_host。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70581228

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档