Please could some one help with this issue. Thanks.
The PHP script below gives rise to the following error when attempting to execute the bulkwrite line.
[russell@hawk mongo]$ cat error_log
[29-Apr-2023 05:04:22 UTC] PHP Fatal error: Uncaught MongoDBDriverExceptionConnectionTimeoutException: No suitable servers found (`serverSelectionTryOnce` set): [connection closed calling ismaster on 'cluster0-shard-00-00.tx3cl.mongodb.net:27017'] [connection closed calling ismaster on 'cluster0-shard-00-01.tx3cl.mongodb.net:27017'] [connection closed calling ismaster on 'cluster0-shard-00-02.tx3cl.mongodb.net:27017'] in /home/mongo/2_test_mongo.php:13
Stack trace:
#0 /home/mongo/2_test_mongo.php(13): MongoDBDriverManager->executeBulkWrite()
#1 {main}
thrown in /home/mongo/2_test_mongo.php on line 13
It is interesting that the error shows a port number. It’s also interesting that the connection string printed back to the console doesn’t have the +srv.
But you are not allowed to include a port number with a mongo+srv
connection type. I am not specifying a port number.
In Compass on the laptop I get this error when taking away the +srv
getaddrinfo ENOTFOUND cluster0.tx3cl.mongodb.net
and also if I add the port number 27017 to make up for the lack of +srv, I get the same error.
Is there something I have to do to override the default port being added?
Technical details
[prompt]$ php --version
PHP 8.0.18 (cli) (built: Apr 13 2022 10:54:57) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.18, Copyright (c) Zend Technologies
[prompt]$ uname -a
Linux blah.blah.net 3.10.0-962.3.2.lve1.5.67.el7.x86_64 #1 SMP Fri Mar 25 07:13:21 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
[prompt]$
The output of the script on the console is as follows
[prompt]$ php script.php
loaded
MongoDBDriverManager Object
(
[uri] => mongodb://user:[email protected]/?retryWrites=true&w=majority
[cluster] => Array
(
)
)
The script itself is
<?php
use MongoDBClient;
use MongoDBDriverServerApi;
echo extension_loaded("mongodb") ? "loadedn" : "not loadedn";
$uri = 'mongodb+srv://user:[email protected]/?retryWrites=true&w=majority';
$manager = new MongoDBDriverManager($uri);
print_r($manager);
$bulk = new MongoDBDriverBulkWrite();
$bulk->insert(['x' => 1]);
$bulk->insert(['x' => 2]);
$bulk->insert(['x' => 3]);
$manager->executeBulkWrite('TestyDB.TestyCollection', $bulk);
$filter = ['x' => ['$gt' => 1]];
$options = [
'projection' => ['_id' => 0],
'sort' => ['x' => -1],
];
$query = new MongoDBDriverQuery($filter, $options);
$cursor = $manager->executeQuery('TestyDB.TestyCollection', $query);
foreach ($cursor as $document) {
var_dump($document);
}
?>
The URL in the connection string is pingable from the server I am trying to connect from.
russell@hawk mongo]$ ping cluster0-shard-00-00.tx3cl.mongodb.net
PING ec2-52-55-183-242.compute-1.amazonaws.com (52.55.183.242) 56(84) bytes of data.
64 bytes from ec2-52-55-183-242.compute-1.amazonaws.com (52.55.183.242): icmp_seq=1 ttl=228 time=76.7 ms
64 bytes from ec2-52-55-183-242.compute-1.amazonaws.com (52.55.183.242): icmp_seq=2 ttl=228 time=76.7 ms
64 bytes from ec2-52-55-183-242.compute-1.amazonaws.com (52.55.183.242): icmp_seq=3 ttl=228 time=76.7 ms
64 bytes from ec2-52-55-183-242.compute-1.amazonaws.com (52.55.183.242): icmp_seq=4 ttl=228 time=76.7 ms
64 bytes from ec2-52-55-183-242.compute-1.amazonaws.com (52.55.183.242): icmp_seq=5 ttl=228 time=76.6 ms
2
Answers
I just changed the version of PHP from 8.0 to 7.4.
The simple answer is that the script works with PHP 7.4. The hint it wasn't a network issue is down to the fact that the same connection string works from a laptop running compass.
The question is now, what is the right syntax for PHP8.0 :-)
I have posted a question to the monog forums here if anyone is interested. https://www.mongodb.com/community/forums/t/why-does-php-8-0-remove-the-srv/224252
What helped me work out the problem with versions was seeing the same code here: https://help.ovhcloud.com/csm/en-gb-public-cloud-databases-mongodb-connect-php?id=kb_article_view&sysparm_article=KB0049087 They stated the version of PHP they were using and the code was essentually the same as what I had.
Previous to this I thought I had done my research for PHP 8.0 and Mongo. Now, if I did, and it's a bug that will be interesting. Can't wait to see what the mongo forums say.
tl;dr: I see no evidence of a driver bug, nor any behavioral difference between PHP 7.4 and 8.0. The root cause appeared to be a restrictive network policy on the PHP 8.0 application server (per your answer).
Explaining the ConnectionTimeoutException
The MongoDB PHP Library docs include an FAQ, which has a section on Server Selection Failures. Reading through that should allow you to make sense of the "No suitable servers found" error, but I’ll break it down here as well:
The driver was unable to select any server for the database operation and is reporting the most recent error on each server connection. The fact that three servers are present here tells us that the original
mongodb+srv://
URI was successfully resolved into a seed list of three hosts.Seeing "connection closed" in the socket error message leads me to assume something immediately rejected the connection. Among the many possible causes for that may be a restrictive network configuration, firewall, or the remote host rejecting a connection. With respect to MongoDB Atlas, this error is also common if PHP application server’s IP address is not included in the cluster’s IP Access List Entries.
Identifying the root cause
In your answer you stated:
If I understand correctly, your hosting company’s network configuration was blocking PHP from making outgoing connections to port 27017. That certainly would have explained the connection error, and doesn’t suggest any issue with PHP or the MongoDB driver.
Clearing up some misunderstandings
The hosts and ports found in the server selection error are not directly related to the
mongodb+srv://
URI. You are overlooking that the driver is going to query DNS and construct a seed list, akin to amongodb://
URI. DNS Seed List Connection Format in the MongoDB docs explains that in more detail.27017
is merely the default port.You’re correct that a
mongodb+srv://
URI does not include the port. The port for each server in the seed list is actually obtained from the DNS records.Note that the seed list is still just an intermediary source of information and may not reflect all servers that the driver ultimately connects to. If you’re curious about that you can read through the Server Discovery and Monitoring driver specification or Server Discovery and Monitoring In Next Generation MongoDB Drivers on the MongoDB blog (it’s a bit old but easier to digest than the raw spec).
I don’t have an explanation for this based on what you shared above, but I also found no evidence that the driver would report anything other than the original URI used to construct the Manager.
The Manager object’s
get_debug_info
handler populates theuri
field usingmongoc_uri_get_string()
). That function in libmongoc (the C driver upon which the PHP driver is built) returns the same string used to construct the URI, which is originally set inmongoc_uri_new_with_error()
. For the record, that is the same function used by the PHP driver when creating a Manager object.I assume some other vital information is being omitted. For example, you mentioned which PHP versions were being used (7.4 and 8.0), but never mentioned the version of the PHP driver (i.e.
mongodb
extension) running in each environment. It also wasn’t clear where each PHP environment was running. If the original connection error was caused by your hosting company’s network configuration, and they happened to be running PHP 8.0, that doesn’t mean that PHP 8.0 is the problem (correlation does not imply causation).The host used for a
mongodb+srv://
URI is not necessarily the same as the host(s) running MongoDB.cluster0.tx3cl.mongodb.net
is used for DNS resolution, but based on the ConnectionTimeoutException above we can see the actual servers are running on the following hosts:Given that, there’s no reason to expect a MongoDB server to be listening on
cluster0.tx3cl.mongodb.net:27017
.