【问题标题】:How Laravel maintains persistent database connectionLaravel 如何维护持久的数据库连接
【发布时间】:2018-12-06 01:12:02
【问题描述】:

我正在本地机器(我的笔记本电脑)上使用 LAMP 设置开发 Laravel 应用程序。

出于测试目的,我尝试使用Aws RDS 的mysql 服务而不是我本地的mysql server。发现,只有一个没有连接的 db 调用的 API 调用(查询:show tables) - 平均需要 12 秒。这是荒唐的。当我使用本地 mysql 服务器时,它大约是 600 毫秒。到目前为止,尚未启用 PDO::ATTR_PERSISTANT。

登录Illuminate\Database\Connectors\Connector.php [里面createConnection()方法],我发现,每个请求都会调用这个方法。这适用于两个mysql服务器。

然后,我将PDO::ATTR_PERSISTANT 设置为true。但是响应时间是相似的。

仔细查看后,发现在同一个文件中:

/**
 * Create a new PDO connection instance.
 *
 * @param  string  $dsn
 * @param  string  $username
 * @param  string  $password
 * @param  array  $options
 * @return \PDO
 */
protected function createPdoConnection($dsn, $username, $password, $options)
{
    if (class_exists(PDOConnection::class) && ! $this->isPersistentConnection($options)) {
        return new PDOConnection($dsn, $username, $password, $options);
    }

    return new PDO($dsn, $username, $password, $options);
}

PDOConnection - extends PDO,当persistent为假时使用 - 构造函数是:

public function __construct($dsn, $user = null, $password = null, array $options = null)
{
    try {
        parent::__construct($dsn, $user, $password, $options);
        $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['Doctrine\DBAL\Driver\PDOStatement', []]);
        $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    } catch (\PDOException $exception) {
        throw new PDOException($exception);
    }
}

看来,将PDO::ATTR_PERSISTANT 设置为true 无效。 这让我很困惑。

  1. 持久性数据库连接在 Laravel 中的实际作用是什么?
  2. 响应时间长的原因是什么(使用Aws RDS的mysql服务)?

【问题讨论】:

    标签: mysql laravel-5 amazon-rds


    【解决方案1】:

    MySQL 是一个以具有轻量级连接开销而闻名的数据库。出于这个原因,关于连接重用的担忧很少出现,但无论如何,PHP 中的连接都与进程相关联。你真的只会看到负载下连接重用的好处,其中有足够多的 php 进程运行,持续的 PHP 进程可以重新使用 mysql 客户端连接。

    换句话说,您的 mysql 客户端连接可以/将/可能会关闭,具体取决于您的 Web 服务器配置,即使您使用的是持久 mysql 连接,或者如果请求的 apache 进程确实需要发生新连接还没有可用的持久连接。

    即使您有可用的持久连接,这并不意味着在您的场景中事情会更快,因为您所做的假设是 通过公共互联网连接到 RDS 的时间很慢,实际上,从您的 localhost 应用程序跨公共互联网的整个 mysql 客户端连接速度很慢。查询会很慢,结果集提取会很慢,总体来说体验会很差。

    如果您在 AWS 上托管整个站点并使用 RDS 作为数据存储,您不会看到需要 12 秒的连接。这将更接近您在本地数据库上使用本地数据库获得的性能类型。

    此外,这个想法的整个谓词都不好。

    1. RDS 是一款高价产品。您根本不应该将其用于开发。如果您使用免费层,那么除了小型数据库之外的任何数据库性能都会非常缓慢。
    2. MySQL 本质上没有网络层安全性。您的 AWS 部署应使用 VPC,其中 RDS 在 VPC 中,您的 PHP 应用程序服务器在 VPC 中。
    3. 在您的应用中使用 RDS 并没有什么特别之处。它在您的应用程序中看起来就像任何其他带有非 localhost -h 参数的 mysql 数据库一样。

    您正在尝试调整在现实世界中几乎没人会使用的东西,因此您正在尝试解决您自己制造的对您的项目没有长期利益的问题。

    话虽如此,如果您想更好地了解您为什么会遇到这种情况,以及 PHP 和相关资源句柄是如何工作的,那么一个具有重量级且耗时的连接过程的数据库就是 Oracle。合法地使用 Oracle 和 PHP 的人必须关心连接重用,因为 Oracle 期望建立一个连接,然后会发生许多“会话”。虽然这个Oracle Cookbook article 现在有点老了,但它很好地说明了 PHP 进程(至少与 Apache 和 Mod_php 之间)和数据库连接之间的关联。

    最后但并非最不重要的一点是,这个主题很复杂,因为您可以通过多种不同的方式运行 PHP。 Apache有几种不同的配置,这与IIS不同,与近几年流行的Nginx/php-fpm不同。 This SO question/answer 已经解决了您尝试使用的特定 PDO 参数,它最终只是将其传递给 MySQL 客户端库,以及一些重要的警告和担忧,解释了为什么 MySQL 连接很少值得它们可能引起的潜在麻烦。

    【讨论】:

    • 仅供参考,我有用于生产目的的 aws-rds 付费服务。正如我所提到的,正在尝试进行实验。另一点是,我并没有试图解决任何问题,而是深入挖掘,事情实际上是如何运作的。大多数时候,攻击性语言无济于事。顺便说一句,感谢您阅读了一个很长的问题并写了一个答案。
    • @MASh:如果您将我写的任何内容视为攻击性内容,我们深表歉意。有时,我只是想保持高效和直率。我们本可以花时间用 10 个问题来梳理您的来源,但我试图在我的 SO 活动中限制这一点。
    • FWIW,我已经和我的大多数客户一起使用 AWS 6 年多了,而 RDS,无论客户是否付费,都非常昂贵,所以我不使用除非是生产。例如,我现在每天为一个客户端停止开发 RDS,只有在我实际使用它时才启动它。希望我关于其使用的观点将帮助您找出最佳实践,即。在 VPC 中使用它。
    • 我也不使用 RDS 进行开发。这次我尝试了,因为这是我们开发团队的决定(我希望我能公开谈论这个原因)
    • 可以将它用于开发,也许有一个开发/测试平台,您的应用服务器也在 AWS 中。您发现的问题是当您尝试本地开发到 RDS 时;)不这样做的论点在我的回答中——公共互联网上的 MySQL 实际上是在泄露您的数据,除非您将其全部包装在 SSL 中。这将是你对他们的论据,为什么这对开发人员来说是个坏主意。 ;)
    猜你喜欢
    • 2011-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-10
    • 1970-01-01
    • 1970-01-01
    • 2010-09-21
    相关资源
    最近更新 更多