PHP Fatal error: Uncaught exception 'MongoWriteConcernException'

593 views
Skip to first unread message

Essence Valencia

unread,
Jan 10, 2015, 11:19:23 PM1/10/15
to mongod...@googlegroups.com

Hello everybody. Has anyone seen this error message before?

PHP Fatal error:  Uncaught exception 'MongoWriteConcernException' with message 'example.domain.com:27017: not master' in /srv/webcore/vendor/zendframework/zendframework/library/Zend/Session/SaveHandler/MongoDB.php:159\nStack trace:\n#0 /srv/webcore/vendor/zendframework/zendframework/library/Zend/Session/SaveHandler/MongoDB.php(159): MongoCollection->update(Array, Array, Array)\n#1 [internal function]: Zend\\Session\\SaveHandler\\MongoDB->write('o0f3a9g3u5lv8a4...', '')\n#2 /srv/webcore/vendor/zendframework/zendframework/library/Zend/Session/SessionManager.php(166): session_write_close()\n#3 [internal function]: Zend\\Session\\SessionManager->writeClose()\n#4 {main}\n  thrown in /srv/webcore/vendor/zendframework/zendframework/library/Zend/Session/SaveHandler/MongoDB.php on line 159

Our site keeps going down whenever the master steps down. We have a total of 3 servers behind this replica set. One master and two slaves. The following is what we would like to have in our /etc/php.ini

[mongo]

mongo.default_host = ""mongodb://example1.domain.com:27017,example2.domain.com:27017,example3.domain.com:27017",array("replicaSet"=>"rs0")"

But unfortunately, the only way to make it work is by setting /etc/php.ini to point directly to the master or otherwise it will fail randomly with the message above until it lands on the master server.

[mongo]

mongo.default_host = example3.domain.com

We would really appreciate any help or leads.

---

PHP Version => 5.5.17

PHP Mongo Driver Version => 1.5.5

Mongo Server Version => 2.6.4

Environment AWS EC2 RedHat


Essence Valencia

unread,
Jan 12, 2015, 11:31:10 AM1/12/15
to mongod...@googlegroups.com
I did some research and this can't be done for PHP. 

---

 

"You can't use PHP.ini to set mongo.default_host if you use the option array. For example:

$mongo = new Mongo(); // Uses mongo.default_host
$mongo = new Mongo(NULL, ['replicaSet' => 'myReplicaSet']); // Does not

This makes configuring groups of machines difficult if they want to use the same PHP code but reference different Mongo servers (configured per-machine with the INI).

While it would be super-awesome to add a new PHP.ini variable mongo.default_replicaSet this wouldn't solve the problem if you wanted to configure any of the other options (username or password for example)

The source-code shows that this issue is actually somewhat by-design:

mongo.c(307) looks something like:

// If someone accidently does something like $hst instead of $host, we'll get
// the empty string.
if (server && strlen(server) == 0) 

{ zend_throw_exception(mongo_ce_ConnectionException, "no server name given", 1 TSRMLS_CC); }

The problem of course is that 

$mongo = new Mongo(NULL, ['replicaSet' => 'myReplicaSet']);

Ends up making server an empty string (not NULL) because technically the option was passed in (not just an optional paramter that wasn't supplied). This in turn prevents you from getting to the nice fallback in php_mongo_parse_server.

The other thing I tried was variations on

$mongo = new Mongo('mongodb://' . Mongo::DEFAULT_SERVER, ['replicaSet' => 'myReplicaSet']);

Except this doesn't work becaus the Mongo::DEFAULT_SERVER constants aren't updated by the PHP.ini variables.

Personally I think the zend_throw_exception cited above is overzealous (albiet well-intentioned) and should be removed. Alternatively you could overload the constructor so that you support "|szbb" or "z" and just put everything in the option array.

Alternatively you could jam defaults for all the ctor-options (replicaSet, username, password, timeout, db) but that might be more work."



Derick Rethans

unread,
Jan 12, 2015, 3:27:24 PM1/12/15
to mongod...@googlegroups.com
mongo.default_host/port only works for single host configurations, not
for replicasets.

For replicasets you need to put multiple hosts in the connection string
that you pass to the MongoClient constructor, and specify the
replicasSet => 'rs0' option:

$client = new MongoClient(
"replicaSet"=>"rs0",
)
);

You can leave out the :27017 though (three times), as that is the
default port.

cheers,
Derick

--
{
website: [ "http://mongodb.org", "http://derickrethans.nl" ],
twitter: [ "@derickr", "@mongodb" ]
}
Reply all
Reply to author
Forward
0 new messages