[JAVA-788] Detecting Server Going Away? Created: 15/Mar/13  Updated: 12/Jul/13  Resolved: 12/Jul/13

Status: Closed
Project: Java Driver
Component/s: Connection Management
Affects Version/s: 2.10.1
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Alan Williamson Assignee: Unassigned
Resolution: Duplicate Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Duplicate
duplicates JAVA-805 Make connection pool and connection s... Closed

 Description   

The Java driver is great when everything goes right. However, the weakness can be seen when things start to go wrong.

Let me illustrate with an example. A very simple one ... detecting when the server is available. You can't!

Say for example you wanted to make sure the server was available (maybe you start your client before the server, or the server goes away for maintenance for a few moments (backup)).

Take the following piece of code:

try{
mongo.getConnector().requestEnsureConnection();
}catch(Exception e){
// never thrown
}

Why is the following exception (see below) masked? It is logged out to the JUL but that is of no use to the calling application.

The mongo.getConnector().isOpen() also suffers the same fate.

Why on earth are these exceptions masked? This is Java 101.

WARNING: Exception executing isMaster command on /127.0.0.1:27017
java.io.IOException: couldn't connect to [/127.0.0.1:27017] bc:java.net.ConnectException: Connection refused: connect
at com.mongodb.DBPort._open(DBPort.java:214)
at com.mongodb.DBPort.go(DBPort.java:107)
at com.mongodb.DBPort.go(DBPort.java:88)
at com.mongodb.DBPort.findOne(DBPort.java:143)
at com.mongodb.DBPort.runCommand(DBPort.java:148)
at com.mongodb.DBTCPConnector.initDirectConnection(DBTCPConnector.java:548)
at com.mongodb.DBTCPConnector.checkMaster(DBTCPConnector.java:527)
at com.mongodb.DBTCPConnector.requestEnsureConnection(DBTCPConnector.java:129)
at com.profiler.ProfilerExtension.run(ProfilerExtension.java:126)
at java.lang.Thread.run(Thread.java:619)

So the question is, how does one handle the fact a server has gone away? What is the magic here to determine what is what?



 Comments   
Comment by Jeffrey Yemin [ 12/Jul/13 ]

Since I didn't get any objections, I'm going to close this as a duplicate of JAVA-805, but please comment if you see a better solution.

Comment by Jeffrey Yemin [ 25/Jun/13 ]

What do you think about marking this as a duplicate of JAVA-805? In my opinion that's the best we can do.

Comment by Jeffrey Yemin [ 15/Mar/13 ]

That method just tells you whether you've called Mongo.close().

Why don't you just send your command and if it fails you know that the server is unavailable? You have to handle failures anyway, as there is no guarantee that the server won't go down between the ping and the next command you send.

Comment by Alan Williamson [ 15/Mar/13 ]

On that vein the mongo.getConnector().isOpen() is another method that doesn't help either in this particular instance.

Since the background thread is continually listening, then to even know if that connection is still alive is a huge leap forward in performance/efficiency than having to always send a "ping" before you send your command.

Comment by Jeffrey Yemin [ 15/Mar/13 ]

Since servers can go off-line at any time, the only guarantee the driver provides is that when you actually try to communicate with the server (by initiating a command, a query, an insert, etc), you will get an exception if it fails. So one thing you might try is a ping command, e.g.

public static void main(String[] args) throws UnknownHostException {
        Mongo m = new Mongo("localhost:3000");
        try {
            m.getDB("admin").command("ping");
        } catch (MongoException.Network e) {
            // You should get this exception if the server is unavailable
            e.printStackTrace();
        }
    }

DB.requestEnsureConnection is a bit of a misnomer, and could certainly be documented better. All it guarantees is that the current thread reserves one of the pooled DBPort instances, each of which wraps a Socket. But the socket is not actually opened until the first time you try to use it to perform some operation.

Generated at Thu Feb 08 08:53:04 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.