对于我们服务器堆栈的相关部分,我们正在运行:
- NGINX 1.2.3
- PHP-FPM 5.3.10 和 PECL mongo 1.2.12
- MongoDB 2.0.7
- CentOS 6.2
当 MongoDB 服务器消失(崩溃、被杀死等)时,我们会遇到一些奇怪但可预测的行为。即使try/catch
在连接代码周围有一个块,即:
try
{
$mdb = new Mongo('mongodb://localhost:27017');
}
catch (MongoConnectionException $e)
{
die( $e->getMessage() );
}
$db = $mdb->selectDB('collection_name');
根据已经连接到 mongo 的 PHP-FPM 工作人员,连接状态被缓存,导致进一步的异常未处理,因为$mdb
无法使用连接处理程序。令人不安的是,在try
相当长的一段时间内,最多 15 分钟后,当 php-fpm 进程死亡/重生时——我假设——时,它并没有持续失败。
本质上,行为是,当您遇到尚未连接到 mongo 的工作人员时,您会收到上面的 die 消息,而当您连接到已连接的工作人员时,您会收到未处理的异常,$mdb->selectDB('collection_name');
因为 catch 没有运行。
当 PHP 是单个进程时,即通过带有 mod_php 的 Apache,这种行为不会发生。只是为了后代,此时回到 Apache/mod_php 不是我们的选择。
有没有办法解决这种行为?我不希望不同 php-fpm 进程之间的连接状态不一致。
编辑: 当我等待驱动程序在这方面得到修复时,我当前的解决方法是进行快速轮询以确定驱动程序是否可以处理请求,然后加载或不加载 MongoDB 库/运行查询(如果它无法连接) /询问:
try
{
// connect
$mongo = new Mongo("mongodb://localhost:27017");
// try to do anything with connection handle
try
{
$mongo->YOUR_DB->YOUR_COLLECTION->findOne();
$mongo->close();
define('MONGO_STATE', TRUE);
}
catch(MongoCursorException $e)
{
$mongo->close();
error_log('Error connecting to MongoDB: ' . $e->getMessage() );
define('MONGO_STATE', FALSE);
}
}
catch(MongoConnectionException $e)
{
error_log('Error connecting to MongoDB: ' . $e->getMessage() );
define('MONGO_STATE', FALSE);
}