Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Impossible to connect to a single member replica set through PHP library #1557

Open
alterphp opened this issue Dec 17, 2024 · 3 comments
Open

Comments

@alterphp
Copy link

alterphp commented Dec 17, 2024

Bug Report

I'm using a single member replica set MongoDB cluster in my development environment (and also in production in some cases), but replica set is well configured. With mongosh, I can connect to the single member by spefying the replicaSet URI parameter and it works well.

Using PHP driver, if I set a replicaSet option, I get an error No suitable servers found (serverSelectionTryOnce set): [connection refused calling hello on '127.0.0.1:27017']. Topology type: ReplicaSetNoPrimary. But through mongosh, I can check that my single member is obviously seen as PRIMARY :

{
  set: 'rs_dev',
  date: ISODate('2024-12-17T17:09:57.780Z'),
  myState: 1,
  term: Long('16'),
  syncSourceHost: '',
  syncSourceId: -1,
  heartbeatIntervalMillis: Long('2000'),
  majorityVoteCount: 1,
  writeMajorityCount: 1,
  votingMembersCount: 1,
  writableVotingMembersCount: 1,
  optimes: { ... },
  lastStableRecoveryTimestamp: Timestamp({ t: 1734455354, i: 1 }),
  electionCandidateMetrics: { ... },
  members: [
    {
      _id: 0,
      name: '127.0.0.1:27017',
      health: 1,
      state: 1,
      stateStr: 'PRIMARY',
      uptime: 3284,
      optime: { ts: Timestamp({ t: 1734455394, i: 1 }), t: Long('16') },
      optimeDate: ISODate('2024-12-17T17:09:54.000Z'),
      lastAppliedWallTime: ISODate('2024-12-17T17:09:54.533Z'),
      lastDurableWallTime: ISODate('2024-12-17T17:09:54.533Z'),
      syncSourceHost: '',
      syncSourceId: -1,
      infoMessage: '',
      electionTime: Timestamp({ t: 1734452114, i: 1 }),
      electionDate: ISODate('2024-12-17T16:15:14.000Z'),
      configVersion: 1,
      configTerm: 16,
      self: true,
      lastHeartbeatMessage: ''
    }
  ],
  ok: 1,
  '$clusterTime': {...},
  operationTime: Timestamp({ t: 1734455394, i: 1 })
}

Environment

I'm not using TLS in dev environment, MongoDB is a Docker container (version 7.0) configured with configured rs_dev ReplicaSet.

Library mongodb/mongodb is 1.19.1
PHP is 8.1
PHP extension is 1.20.1

It seems to be handled the same way by NodeJS driver (same issue described here : https://stackoverflow.com/questions/69531947/replicasetnoprimary-error-although-primary-exists).

Please tell me if this is expected behavior, although mongosh seems OK with single member replica set ?

@alcaeus
Copy link
Member

alcaeus commented Dec 18, 2024

I just tested one of the example scripts with a single-member replica set and was able to connect to it without an issue. Since you mentioned this is in docker, would you be able to share the setup you were using so we can try to reproduce it?

@alterphp
Copy link
Author

alterphp commented Dec 18, 2024

Hello @alcaeus,

And thank you for taking a look !

Here is the Dockerfile of the built image :

FROM mongo:7.0

# Generates a keyfile, mandatory to run as a replica set
RUN openssl rand -base64 756 > /etc/mongo-keyfile
RUN chmod 400 /etc/mongo-keyfile
RUN chown mongodb:mongodb /etc/mongo-keyfile

# Any JS or Shell file found in docker-entrypoint-initdb.d directory is executed
# when container is run the first time
# @see https://hub.docker.com/_/mongo
COPY initiateReplSet.js ./docker-entrypoint-initdb.d/

CMD ["mongod", "--replSet", "rs_dev", "--keyFile", "/etc/mongo-keyfile", "--bind_ip", "0.0.0.0"]

the file initiateReplSet.js contains only one instruction rs.initiate().

The container is served in a Docker Compose stack, with this service definition :

    mongo:
        image: registry.gitlab.com/mycompany/tools/docker-images/mongo/dev:7.0
        ports:
            - '27017:27017'
        volumes:
            - mongo_data:/data/db
        networks:
            - database
        environment:
            MONGO_INITDB_ROOT_USERNAME: root
            MONGO_INITDB_ROOT_PASSWORD: root

The connection string configured in my local web app MONGODB_URL=mongodb://root:root@mongo:27017 and the replicaSet option in the doctrine_mongodb configuration. If I ommit the replica set option in connection configuration, it works fine (but it does not connect to the replica set, it's a direct connection).

And the ConnectionTimeoutError on read action, through Symfony with Doctrine Mongo ODM :
An exception has been thrown during the rendering of a template ("No suitable servers found (serverSelectionTryOnce set): [connection refused calling hello on '127.0.0.1:27017']").

with the head of stack trace

MongoDB\Driver\Exception\ConnectionTimeoutException:
No suitable servers found (`serverSelectionTryOnce` set): [connection refused calling hello on '127.0.0.1:27017']

  at vendor/mongodb/mongodb/src/functions.php:599
  at MongoDB\Driver\Manager->selectServer(object(ReadPreference))
     (vendor/mongodb/mongodb/src/functions.php:599)
  at MongoDB\select_server(object(Manager), array('sort' => array('createdAt' => -1), 'limit' => 100, 'skip' => 0, 'readConcern' => object(ReadConcern), 'readPreference' => object(ReadPreference), 'typeMap' => array('root' => 'array', 'document' => 'array')))
     (vendor/mongodb/mongodb/src/Collection.php:646)
  at MongoDB\Collection->find(array('origin' => 'mobile-app'), array('sort' => array('createdAt' => -1), 'limit' => 100, 'skip' => 0, 'readConcern' => object(ReadConcern), 'readPreference' => object(ReadPreference), 'typeMap' => array('root' => 'array', 'document' => 'array')))
     (vendor/doctrine/mongodb-odm/lib/Doctrine/ODM/MongoDB/Query/Query.php:454)
  at Doctrine\ODM\MongoDB\Query\Query->runQuery()
     (vendor/doctrine/mongodb-odm/lib/Doctrine/ODM/MongoDB/Query/Query.php:205)
  at Doctrine\ODM\MongoDB\Query\Query->execute()
     (vendor/pagerfanta/pagerfanta/lib/Adapter/Doctrine/MongoDBODM/QueryAdapter.php:56)
  at Pagerfanta\Doctrine\MongoDBODM\QueryAdapter->getSlice(0, 100)
     (vendor/pagerfanta/pagerfanta/lib/Core/Pagerfanta.php:337)
  at Pagerfanta\Pagerfanta->getCurrentPageResultsFromAdapter()
     (vendor/pagerfanta/pagerfanta/lib/Core/Pagerfanta.php:323)
  at Pagerfanta\Pagerfanta->getCurrentPageResults()
     (vendor/twig/twig/src/Extension/CoreExtension.php:1754)
  at Twig\Extension\CoreExtension::getAttribute(object(Environment), object(Source), object(Pagerfanta), 'currentPageResults', array(), 'any', false, false, false, 116)

@jmikola
Copy link
Member

jmikola commented Dec 20, 2024

The connection string configured in my local web app MONGODB_URL=mongodb://root:root@mongo:27017 and the replicaSet option in the doctrine_mongodb configuration. If I ommit the replica set option in connection configuration, it works fine (but it does not connect to the replica set, it's a direct connection).

I know you mentioned the "rs_dev" is used as the replica set name, but given the behavior you reported I expect the correct name is not actually being passed to the driver.

You can also test this locally using SDAM logging and tweaking the connection string. Below are two snippets of running examples/sdam_logger.php on a local single-member replica set (named "rs0") with and without the correct replicaSet connection string value. In both cases we observe the host in the seed list added to the topology, but in the example with the incorrect replicaSet value we see it removed since it does not match the setName reported in the host's hello monitoring response.

Correct replicaSet parameter

$ MONGODB_URI='mongodb://127.0.0.1:27080/?replicaSet=rs0' php sdam_logger.php 
topologyOpening: 6765919ee6bcb9197e0a6130 was opened

topologyChanged: 6765919ee6bcb9197e0a6130 changed from Unknown to ReplicaSetNoPrimary

serverOpening: 127.0.0.1:27080 was added to topology 6765919ee6bcb9197e0a6130

serverHeartbeatStarted: 127.0.0.1:27080 heartbeat started

serverHeartbeatSucceeded: 127.0.0.1:27080 heartbeat succeeded after 492µs
reply: { "helloOk" : true, "topologyVersion" : { "processId" : { "$oid" : "6765904e0fd39853caba155d" }, "counter" : 6 }, "hosts" : [ "127.0.0.1:27080" ], "setName" : "rs0", "setVersion" : 1, "ismaster" : true, "secondary" : false, "primary" : "127.0.0.1:27080", "me" : "127.0.0.1:27080", "electionId" : { "$oid" : "7fffffff0000000000000001" }, "lastWrite" : { "opTime" : { "ts" : { "$timestamp" : { "t" : 1734709658, "i" : 1 } }, "t" : 1 }, "lastWriteDate" : { "$date" : "2024-12-20T15:47:38Z" }, "majorityOpTime" : { "ts" : { "$timestamp" : { "t" : 1734709658, "i" : 1 } }, "t" : 1 }, "majorityWriteDate" : { "$date" : "2024-12-20T15:47:38Z" } }, "maxBsonObjectSize" : 16777216, "maxMessageSizeBytes" : 48000000, "maxWriteBatchSize" : 100000, "localTime" : { "$date" : "2024-12-20T15:47:42.917Z" }, "logicalSessionTimeoutMinutes" : 30, "connectionId" : 9, "minWireVersion" : 0, "maxWireVersion" : 25, "readOnly" : false, "ok" : 1.0, "$clusterTime" : { "clusterTime" : { "$timestamp" : { "t" : 1734709658, "i" : 1 } }, "signature" : { "hash" : { "$binary" : { "base64" : "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", "subType" : "00" } }, "keyId" : 0 } }, "operationTime" : { "$timestamp" : { "t" : 1734709658, "i" : 1 } } }

serverChanged: 127.0.0.1:27080 changed from Unknown to RSPrimary
previous hello response: { }
new hello response: { "helloOk" : true, "topologyVersion" : { "processId" : { "$oid" : "6765904e0fd39853caba155d" }, "counter" : 6 }, "hosts" : [ "127.0.0.1:27080" ], "setName" : "rs0", "setVersion" : 1, "ismaster" : true, "secondary" : false, "primary" : "127.0.0.1:27080", "me" : "127.0.0.1:27080", "electionId" : { "$oid" : "7fffffff0000000000000001" }, "lastWrite" : { "opTime" : { "ts" : { "$timestamp" : { "t" : 1734709658, "i" : 1 } }, "t" : 1 }, "lastWriteDate" : { "$date" : "2024-12-20T15:47:38Z" }, "majorityOpTime" : { "ts" : { "$timestamp" : { "t" : 1734709658, "i" : 1 } }, "t" : 1 }, "majorityWriteDate" : { "$date" : "2024-12-20T15:47:38Z" } }, "maxBsonObjectSize" : 16777216, "maxMessageSizeBytes" : 48000000, "maxWriteBatchSize" : 100000, "localTime" : { "$date" : "2024-12-20T15:47:42.917Z" }, "logicalSessionTimeoutMinutes" : 30, "connectionId" : 9, "minWireVersion" : 0, "maxWireVersion" : 25, "readOnly" : false, "ok" : 1.0, "$clusterTime" : { "clusterTime" : { "$timestamp" : { "t" : 1734709658, "i" : 1 } }, "signature" : { "hash" : { "$binary" : { "base64" : "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", "subType" : "00" } }, "keyId" : 0 } }, "operationTime" : { "$timestamp" : { "t" : 1734709658, "i" : 1 } } }

topologyChanged: 6765919ee6bcb9197e0a6130 changed from ReplicaSetNoPrimary to ReplicaSetWithPrimary

topologyClosed: 6765919ee6bcb9197e0a6130 was closed

Incorrect replicaSet parameter

$ MONGODB_URI='mongodb://127.0.0.1:27080/?replicaSet=rs1' php sdam_logger.php 
topologyOpening: 6765908f89a783b4a8029a40 was opened

topologyChanged: 6765908f89a783b4a8029a40 changed from Unknown to ReplicaSetNoPrimary

serverOpening: 127.0.0.1:27080 was added to topology 6765908f89a783b4a8029a40

serverHeartbeatStarted: 127.0.0.1:27080 heartbeat started

serverHeartbeatSucceeded: 127.0.0.1:27080 heartbeat succeeded after 511µs
reply: { "helloOk" : true, "topologyVersion" : { "processId" : { "$oid" : "6765904e0fd39853caba155d" }, "counter" : 6 }, "hosts" : [ "127.0.0.1:27080" ], "setName" : "rs0", "setVersion" : 1, "ismaster" : true, "secondary" : false, "primary" : "127.0.0.1:27080", "me" : "127.0.0.1:27080", "electionId" : { "$oid" : "7fffffff0000000000000001" }, "lastWrite" : { "opTime" : { "ts" : { "$timestamp" : { "t" : 1734709388, "i" : 1 } }, "t" : 1 }, "lastWriteDate" : { "$date" : "2024-12-20T15:43:08Z" }, "majorityOpTime" : { "ts" : { "$timestamp" : { "t" : 1734709388, "i" : 1 } }, "t" : 1 }, "majorityWriteDate" : { "$date" : "2024-12-20T15:43:08Z" } }, "maxBsonObjectSize" : 16777216, "maxMessageSizeBytes" : 48000000, "maxWriteBatchSize" : 100000, "localTime" : { "$date" : "2024-12-20T15:43:11.969Z" }, "logicalSessionTimeoutMinutes" : 30, "connectionId" : 8, "minWireVersion" : 0, "maxWireVersion" : 25, "readOnly" : false, "ok" : 1.0, "$clusterTime" : { "clusterTime" : { "$timestamp" : { "t" : 1734709388, "i" : 1 } }, "signature" : { "hash" : { "$binary" : { "base64" : "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", "subType" : "00" } }, "keyId" : 0 } }, "operationTime" : { "$timestamp" : { "t" : 1734709388, "i" : 1 } } }

serverChanged: 127.0.0.1:27080 changed from Unknown to RSPrimary
previous hello response: { }
new hello response: { "helloOk" : true, "topologyVersion" : { "processId" : { "$oid" : "6765904e0fd39853caba155d" }, "counter" : 6 }, "hosts" : [ "127.0.0.1:27080" ], "setName" : "rs0", "setVersion" : 1, "ismaster" : true, "secondary" : false, "primary" : "127.0.0.1:27080", "me" : "127.0.0.1:27080", "electionId" : { "$oid" : "7fffffff0000000000000001" }, "lastWrite" : { "opTime" : { "ts" : { "$timestamp" : { "t" : 1734709388, "i" : 1 } }, "t" : 1 }, "lastWriteDate" : { "$date" : "2024-12-20T15:43:08Z" }, "majorityOpTime" : { "ts" : { "$timestamp" : { "t" : 1734709388, "i" : 1 } }, "t" : 1 }, "majorityWriteDate" : { "$date" : "2024-12-20T15:43:08Z" } }, "maxBsonObjectSize" : 16777216, "maxMessageSizeBytes" : 48000000, "maxWriteBatchSize" : 100000, "localTime" : { "$date" : "2024-12-20T15:43:11.969Z" }, "logicalSessionTimeoutMinutes" : 30, "connectionId" : 8, "minWireVersion" : 0, "maxWireVersion" : 25, "readOnly" : false, "ok" : 1.0, "$clusterTime" : { "clusterTime" : { "$timestamp" : { "t" : 1734709388, "i" : 1 } }, "signature" : { "hash" : { "$binary" : { "base64" : "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", "subType" : "00" } }, "keyId" : 0 } }, "operationTime" : { "$timestamp" : { "t" : 1734709388, "i" : 1 } } }

serverClosed: 127.0.0.1:27080 was removed from topology 6765908f89a783b4a8029a40

topologyChanged: 6765908f89a783b4a8029a40 changed from ReplicaSetNoPrimary to ReplicaSetNoPrimary

PHP Fatal error:  Uncaught MongoDB\Driver\Exception\ConnectionTimeoutException: No suitable servers found (`serverSelectionTryOnce` set). Topology type: ReplicaSetNoPrimary in...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants