Symfony 拒绝数据库连接 / PHP

Database connection refused with Symfony / PHP

正在尝试将 Symfony 3.2/Doctrine 应用程序部署到 Swisscom PaaS。

Buildpack(PHP 7、httpd 等)已安装,composer 是 运行 并安装依赖项,但是在调用 composer 后命令时,如 cache:clear 我得到一个:

[Doctrine\DBAL\Exception\ConnectionException]                              
An exception occured in driver: SQLSTATE[HY000] [2002] Connection refused

我的manifest.yml:

applications:
- services:
 - dbservice
buildpack: php_buildpack
host: myapp
name: MyApp
instances: 1
memory: 640M
env:
 SYMFONY_ENV: prod
 PHP_INI_SCAN_DIR: .bp-config/php/conf.d

我的options.json:

"WEB_SERVER": "httpd",
"COMPOSER_INSTALL_OPTIONS": ["--no-dev --optimize-autoloader --no-progress --no-interaction"],
"COMPOSER_VENDOR_DIR": "vendor",
"SYMFONY_ENV": "prod",
"WEBDIR": "web",
"PHP_MODULES": "fpm",
"PHP_VERSION": "{PHP_70_LATEST}",
"PHP_EXTENSIONS": [
 "bz2",
 "zlib",
 "curl",
 "mcrypt",
 "openssl",
 "mbstring",
 "pdo",
 "pdo_mysql"
],
"ZEND_EXTENSIONS": [
 "opcache"
]

这就是我从 VCAP 读取数据库凭据并在 Symfony 中设置参数的方式(这与 VCAPSERVICES 环境变量的本地设置完美配合):

$vcapServices = json_decode($_ENV['VCAP_SERVICES']);

$container->setParameter('database_driver', 'pdo_mysql');

$db = $vcapServices->{'mariadb'}[0]->credentials;

$container->setParameter('database_host', $db->host);
$container->setParameter('database_port', $db->port);
$container->setParameter('database_name', $db->name);
$container->setParameter('database_user', $db->username);
$container->setParameter('database_password', $db->password);

// Just for debug:

echo 'User: ';
var_dump($container->getParameter('database_user'));

echo 'Db: ';
var_dump($db);

服务 运行,两者都 var_dump 提供了预期的价值。但是仍然拒绝连接。

我做错了什么?

****编辑**** 这里似乎有类似的问题,但没有解决方案:Cloud foundry p-mysql

****编辑****

我一直调试到调用 PDO 构造函数的语句。

使用以下参数调用:

$dsn = mysql:host=10.0.20.18;port=3306;dbname=CF_DB922DD3_CACB_4344_9948_746E585732B5;
$username = "myrealusername"; // as looked up in VCAP_SERVICES
$password = "myrealpassword"; // as looked up in VCAP_SERVICES
$options = array();

在服务绑定的 Web 控制台中,任何看起来都与它完全相同的东西。

是否需要 unix_socket 才能成功连接?

****编辑****

由于 Symfony 正在使用一些 composer post-install-commands(在这种情况下,例如清除和预热缓存),这需要一个有效的数据库连接,而 cloudfoundry 的数据库服务不支持它只要容器没有完全构建和部署?

我 运行 没主意了。

根据我的经验,Connection refused 可能意味着以下情况之一:

  • 防火墙 (iptables?) 阻止非本地访问端口
  • mysql 服务器甚至没有监听端口
  • mysql 服务器正在侦听 ipv6 端口 3306,而客户端尝试通过 ipv4 连接。

首先让我们尝试通过 运行 基本 telnet 测试缩小范围:

telnet 10.0.20.18 3306

这应该会以一些含糊不清的消息向您致意,其中清楚地提到了 MySQL。如果没有,则您需要返回更一般的限制,例如防火墙和策略。

既然您确定服务器是 运行,我建议检查您是否被防火墙或 SELinux 阻止。不过,不知道您对 Swisscom 的 PaaS 系统有多少控制权。

如果您可以通过 SSH 访问 PaaS 服务,您可以尝试 运行 tcpdump 捕获任何流量。参见这篇文章:https://serverfault.com/questions/507627/debugging-a-connection-refused-response-on-port-21

希望这能给你一些提示...

以防万一有人遇到类似问题,这是解决方案:

最后我只能通过 PaaS 提供商 (swisscomdev) 的支持来解决这个问题。

显然,在我们的应用 staging/deployment 期间,数据库连接不是 provided/possible,但 Symfony 的缓存:clear/warmup 在作曲家 post 处理阶段需要完整的数据库连接.

修复基于 cloudfoundry 的 swisscomdev 平台后,一切都按预期工作。

对这个问题深表歉意,感谢您的反馈。 Swisscom 修改了安全组。有关详细信息,请参阅 Application Security Groups

Cloud Foundry blocks all outbound network connections from application containers by default. Administrators can override this block-by-default behavior with Application Security Groups (ASGs).

ASGs are a collection of egress rules that specify one or more individual protocols, ports, and destinations to allow network access to.

Cloud Foundry has two default sets of ASGs: default-staging and default-running. All application containers in Cloud Foundry use a base policy from one of these.

Galera 即服务 (MariaDB) 的规则仅在 running 中完成。我们也将规则添加到 staging.