Checked on ADS 14-alpha-23.
I am not fully aware how the current replica set connection related implementation works on ADS but below is an observation :
1) Now if we just specify secondary member server/port information on 'Register Server' window and try to connect, the DB objects (Collections, Indexes etc) are not displayed saying 'Not talking to master'. (Pls refer to replset_secondary_exception.png) This should not be the case. Even if just a single secondary member or subset of members of replica set are specified, ADS should intelligently garner primary member information using db.runCommand('isMaster') (or similar command) and connect to it.
(Pls refer to http://docs.mongodb.org/meta-driver/latest/legacy/connect-driver-to-replica-set/ for some details)
Take a look at: https://github.com/mongodb/mongo-snippets/blob/master/java/Test.java
When creating a replicaSet, seems we also need to invoke mongo.slaveOk() method which will then allow Mongo connections to read from secondaries when possible
The above example seems to be outdated now. slaveOK() method has been deprecated.
Emil - here's what I suggest, can you also try this out on a replica set.
-- Drop the "slaveOK" property from our drivers tab.
-- Keep the readPreference property and see if we can get that to work.
Refere to issue 9032 for a simple way to establish a replica set.
The above example seems to be outdated now. slaveOK() method has been deprecated.
Emil - here's what I suggest, can you also try this out on a replica set.
-- Drop the "slaveOK" property from our drivers tab.
-- Keep the readPreference property and see if we can get that to work.
Refere to issue 9032 for a simple way to establish a replica set.
The MongoOptions.slaveOK field and the Mongo.slaveOk() method have been deprecated, indeed, but the MongoClientURI class is still able to parse this JDBC parameter. Setting slaveOK=true in the connect URL will set the readPreference property to secondaryPreferred if there is no such preference defined yet.
Therefore, based on the scenario from #9032, setting either slaveOK=true or readPreference=secondaryPreferred solves the problem from current issue (#9120).
I can remove the slaveOK JDBC parameter if necessary, although it works as an alternative. The description for readPreference parameters clearly underlines this parameter overrides the slaveOK one.
The MongoOptions.slaveOK field and the Mongo.slaveOk() method have been deprecated, indeed, but the MongoClientURI class is still able to parse this JDBC parameter. Setting slaveOK=true in the connect URL will set the readPreference property to secondaryPreferred if there is no such preference defined yet.
Therefore, based on the scenario from #9032, setting either slaveOK=true or readPreference=secondaryPreferred solves the problem from current issue (#9120).
I can remove the slaveOK JDBC parameter if necessary, although it works as an alternative. The description for readPreference parameters clearly underlines this parameter overrides the slaveOK one.
I can remove the slaveOK JDBC parameter if necessary, although it works as an alternative. The description for readPreference parameters clearly underlines this parameter overrides the slaveOK one.
Lets go ahead & remove slaveOK JDBC parameter. B/c we're coming out w/ a v1 release, we can remove it.
I can remove the slaveOK JDBC parameter if necessary, although it works as an alternative. The description for readPreference parameters clearly underlines this parameter overrides the slaveOK one.
Lets go ahead & remove slaveOK JDBC parameter. B/c we're coming out w/ a v1 release, we can remove it.
OK, I'll remove it.
What about Ravi's proposal of using smart queries for detecting the master node of the replica set and connect to it?
As described on the link indicated on issue's description and confirmed by tests made, the isMaster query method would require the following steps:
An alternative to the iterative isMaster query above (until the primary server is found) would be to run the replSetGetStatus on the admin database (i.e. the equiv for rs.status() ) and from the value of the "members' field extract the document having stateStr == "PRIMARY" . I am not sure if in this case is guaranteed that the "name" field of this document always contains a valid host/port pair. After the primary server is established, we still follow the remaining steps described above.
The latter solution requires admin privileges, while the former one works on accounts with limited privileges.
Probably this solution of smart swapping the secondary with the primary server would work, but I think is a bit not recommendable to dynamically change the connection without informing the user about this change.
There is another concern regarding the hostname itself (for the primary server). I am not sure if the hostname obtained from the list of members is always a valid host name reachable by the client or it can be a hostname valid only inside an internal network and thus not reachable by the client.
OK, I'll remove it.
What about Ravi's proposal of using smart queries for detecting the master node of the replica set and connect to it?
As described on the link indicated on issue's description and confirmed by tests made, the isMaster query method would require the following steps:
An alternative to the iterative isMaster query above (until the primary server is found) would be to run the replSetGetStatus on the admin database (i.e. the equiv for rs.status() ) and from the value of the "members' field extract the document having stateStr == "PRIMARY" . I am not sure if in this case is guaranteed that the "name" field of this document always contains a valid host/port pair. After the primary server is established, we still follow the remaining steps described above.
The latter solution requires admin privileges, while the former one works on accounts with limited privileges.
Probably this solution of smart swapping the secondary with the primary server would work, but I think is a bit not recommendable to dynamically change the connection without informing the user about this change.
There is another concern regarding the hostname itself (for the primary server). I am not sure if the hostname obtained from the list of members is always a valid host name reachable by the client or it can be a hostname valid only inside an internal network and thus not reachable by the client.
What about Ravi's proposal of using smart queries for detecting the master node of the replica set and connect to it?
Emil - I thought the purpose of setting the readPreference is so that the mongo java implementation would take care of this logic and we wouldn't not need to implement it in our JDBC client. Is this not the case?
What about Ravi's proposal of using smart queries for detecting the master node of the replica set and connect to it?
Emil - I thought the purpose of setting the readPreference is so that the mongo java implementation would take care of this logic and we wouldn't not need to implement it in our JDBC client. Is this not the case?
From Ravi's request, I understood that is desired that ADS automatically connect to the master server when queries fail on the secondary node, without requiring any specific properties to be set by the user.
The slaveOK or readPreference JDBC parameters solve this issue if these parameters are properly set. Actually, this is the main purpose for their existence: to allow read operations on secondary nodes:
http://docs.mongodb.org/manual/reference/method/rs.slaveOk/
http://docs.mongodb.org/manual/core/read-preference/#secondaryPreferred
I also consider setting the readPreference parameter (as slaveOK will be removed) is better than finding the master and connecting to it, as this fallback doesn't work if the primary server is down (issue #9032).
From Ravi's request, I understood that is desired that ADS automatically connect to the master server when queries fail on the secondary node, without requiring any specific properties to be set by the user.
The slaveOK or readPreference JDBC parameters solve this issue if these parameters are properly set. Actually, this is the main purpose for their existence: to allow read operations on secondary nodes:
http://docs.mongodb.org/manual/reference/method/rs.slaveOk/
http://docs.mongodb.org/manual/core/read-preference/#secondaryPreferred
I also consider setting the readPreference parameter (as slaveOK will be removed) is better than finding the master and connecting to it, as this fallback doesn't work if the primary server is down (issue #9032).
Ravi, you should use this JDBC parameter: readPreference=secondaryPreferred to be able to run queries on secondary nodes.
Ravi, you should use this JDBC parameter: readPreference=secondaryPreferred to be able to run queries on secondary nodes.
http://docs.mongodb.org/manual/core/read-preference/#primaryPreferred
Ravi - please also try readPreference=primaryPreferred
Assuming primaryPreferred works as documented, I'll ask Asif or Jenny to change the code so that if the user chooses ReplicaSet in ADS GUI, the GUI will pass into the Mongo JDBC driver readPreference=primaryPreferred
http://docs.mongodb.org/manual/core/read-preference/#primaryPreferred
Ravi - please also try readPreference=primaryPreferred
Assuming primaryPreferred works as documented, I'll ask Asif or Jenny to change the code so that if the user chooses ReplicaSet in ADS GUI, the GUI will pass into the Mongo JDBC driver readPreference=primaryPreferred
When the primary server is down and one tries an ADS connection to a secondary MongoDB server, either readPreference=primaryPreferred or readPreference=secondaryPreferred works with one condition: the connection type is "Stand Alone" or a single server (the secondary one) is specified for the "Replica Set" type.
If multiple servers are specified (not covered on this issue, but by #9032), the exception from #9032 is thrown and no ADS connection is established.
When the primary server is down and one tries an ADS connection to a secondary MongoDB server, either readPreference=primaryPreferred or readPreference=secondaryPreferred works with one condition: the connection type is "Stand Alone" or a single server (the secondary one) is specified for the "Replica Set" type.
If multiple servers are specified (not covered on this issue, but by #9032), the exception from #9032 is thrown and no ADS connection is established.
Ok, I understand now what is happening. The issue referred to in #9032 is simply a diagnostic issue -- we added additional diagnostic checking but didn't do anything for handling multiple servers in our diagnostic testing. Asif will take care of that in issue 9134
To test our readPreference, create a replica set with multiple members and then click the "Save" button. You'll get a diagnostic warning message. Click "Save Anyways" and your server registration will be saved. Now see if the readPreference setting works in this situation.
Ok, I understand now what is happening. The issue referred to in #9032 is simply a diagnostic issue -- we added additional diagnostic checking but didn't do anything for handling multiple servers in our diagnostic testing. Asif will take care of that in issue 9134
To test our readPreference, create a replica set with multiple members and then click the "Save" button. You'll get a diagnostic warning message. Click "Save Anyways" and your server registration will be saved. Now see if the readPreference setting works in this situation.
No, the exception from #9032 is not related to the "Test Connection" problem from #9134. Even if I click on "Save Anyway", the exception is still thrown when I try a to open an instance for this connection (from Schema Browser or open a Query Analyzer window).
The exception is caused by the DB.getDatabaseNames() ( the listDatabases command). I've mentioned it here just to let you know that the readPreference=[primary | secondary]Preferred option doesn't always fully work because it depends on issue #9032. It works for the particular scenario from the description of this issue (single server provided).
No, the exception from #9032 is not related to the "Test Connection" problem from #9134. Even if I click on "Save Anyway", the exception is still thrown when I try a to open an instance for this connection (from Schema Browser or open a Query Analyzer window).
The exception is caused by the DB.getDatabaseNames() ( the listDatabases command). I've mentioned it here just to let you know that the readPreference=[primary | secondary]Preferred option doesn't always fully work because it depends on issue #9032. It works for the particular scenario from the description of this issue (single server provided).
We have done some testing with replica set.
For this scenario to work, you need to set readPreference=primaryPreferred. The default is readPreference=primary, which doesn't work.
Emil, please change the default for the readPreference parameter to primaryPreferred (to help reduce the number of support calls later) and also remove the slaveOK parameter.
We have done some testing with replica set.
For this scenario to work, you need to set readPreference=primaryPreferred. The default is readPreference=primary, which doesn't work.
Emil, please change the default for the readPreference parameter to primaryPreferred (to help reduce the number of support calls later) and also remove the slaveOK parameter.
The readPreference parameter has now the primaryPreferred as the default value . Removed the slaveOK JDBC parameter.
The readPreference parameter has now the primaryPreferred as the default value . Removed the slaveOK JDBC parameter.
The slaveOK parameter is back in for issue #9032.
The slaveOK parameter is back in for issue #9032.
Hi Emil/Jenny,
I was trying to verify this issue in ADS 14-beta-55 and have a query as follows:
1) Now that ADS has default readPreference = primaryPreferred, could you please inform how ADS should behave in following situation?
There is a 3 member replicaset : localhost:27021, localhost:27023, localhost:27024 and currently only 27021 is active as secondary. On ADS, user specifies replica set servers as localhost:27023 , localhost:27021.
Does the user still needs to set slaveOK=true on ADS to connect to solely existing secondary member (27021)?
My expectation was that with readPreference = primaryPreferred, the user would be able to connect to sec member without setting slaveOK = true but it's not so (slaveOK still needs to be true to be able to connect to sec)
Hi Emil/Jenny,
I was trying to verify this issue in ADS 14-beta-55 and have a query as follows:
1) Now that ADS has default readPreference = primaryPreferred, could you please inform how ADS should behave in following situation?
There is a 3 member replicaset : localhost:27021, localhost:27023, localhost:27024 and currently only 27021 is active as secondary. On ADS, user specifies replica set servers as localhost:27023 , localhost:27021.
Does the user still needs to set slaveOK=true on ADS to connect to solely existing secondary member (27021)?
My expectation was that with readPreference = primaryPreferred, the user would be able to connect to sec member without setting slaveOK = true but it's not so (slaveOK still needs to be true to be able to connect to sec)
Does the user still needs to set slaveOK=true on ADS to connect to solely existing secondary member (27021)?My expectation was that with readPreference = primaryPreferred, the user would be able to connect to sec member without setting slaveOK = true but it's not so (slaveOK still needs to be true to be able to connect to sec)
Does the user still needs to set slaveOK=true on ADS to connect to solely existing secondary member (27021)?My expectation was that with readPreference = primaryPreferred, the user would be able to connect to sec member without setting slaveOK = true but it's not so (slaveOK still needs to be true to be able to connect to sec)
Issue #9120 |
Closed |
Fixed |
Resolved |
Completion |
No due date |
Fixed Build ADS 14.0.0-beta-11 (mongo-jdbc 1.1.9) |
No time estimate |
1 issue link |
relates to #9032
Issue #9032ADS not able to connect to secondary member when primary of repl set is down |
Take a look at: https://github.com/mongodb/mongo-snippets/blob/master/java/Test.java
When creating a replicaSet, seems we also need to invoke mongo.slaveOk() method which will then allow Mongo connections to read from secondaries when possible