I'm working with the java Mongo driver 3.2 and I'm trying to figure out exactly what I should have multiple instances of and what should be persisted across the app.
So, for example, MongoClient says that there should be only one instance for the app. It also says that it establishes a connection pool. Which is great. When are those connections actually made? I want to make sure I'm effectively using the pool.
So is the connection to the DB made when I do MongoClient#getDataBase? MongoDatabase#getCollection? Or some time when I perform an action on the collection itself, such as .find?
What should be saved off? Should I have multiple instances of the Database? the Collection? or is it just the client?
Mainly I'm trying to make sure that I don't limit myself to one connection but that I also don't spam the database unnecessarily.
Once instance should be fine per application. MongoDB Driver Quick Tour - Java seems clear enough. EDIT: My understanding of the writing is that when you call MongoClient.getDB(); is when you are connecting, to be sure parsing through their source code if available to see the exact moment. EDIT 2: Added links to MongoDB Java Driver which is here MongoDB Driver and particularly the class your checking for is MongoClient which extends Mongo.class which is where the .getDB(); is located; in this method they check the DB Cache and if not they create a new DB.class Instance. After running through the code it appears in the Mongo.class constructor so when you call new MongoClient(); they call connector.start()
public Mongo( ServerAddress addr , MongoOptions options )
throws MongoException {
_addr = addr;
_addrs = null;
_options = options;
_applyMongoOptions();
_connector = new DBTCPConnector( this , _addr );
_connector.start();
_cleaner = new DBCleanerThread();
_cleaner.start();
}
From their page
// To directly connect to a single MongoDB server (note that this will not auto-discover the primary even
// if it's a member of a replica set:
MongoClient mongoClient = new MongoClient();
// or
MongoClient mongoClient = new MongoClient( "localhost" );
// or
MongoClient mongoClient = new MongoClient( "localhost" , 27017 );
// or, to connect to a replica set, with auto-discovery of the primary, supply a seed list of members
MongoClient mongoClient = new MongoClient(Arrays.asList(new ServerAddress("localhost", 27017),
new ServerAddress("localhost", 27018),
new ServerAddress("localhost", 27019)));
DB db = mongoClient.getDB( "mydb" );
At this point, the db object will be a connection to a MongoDB server
for the specified database. With it, you can do further operations.
The MongoClient class is designed to be thread safe and shared among
threads. Typically you create only 1 instance for a given database
cluster and use it across your application.
important
When creating many MongoClient instances:
All resource usage limits (max connections, etc) apply per MongoClient instance
To dispose of an instance, make sure you call MongoClient.close() to clean up resources
Related
I am a server-side developer, working on a project which uses a mongo cluster as persistent database.
I have a question for https://mongodb.github.io/mongo-java-driver/3.8/javadoc/com/mongodb/connection/ConnectionPoolSettings.html
It said to a MongoDB server
But what if I have a connectionString like following one
mongodb://user:pwd#mongos1:port,mongos3:port,mongos3:port,mongos4:port,mongos5:port,mongos6:port/admin?readPreference=secondaryPreferred
A mongodb sharded cluster which has 6 mongos instance.
Question:
Is the connectionPoolSetting related to one mongos server? or related to all mongos servers?
E.g. if we have maxSize = 10 in this setting, does it mean single client has max connection pool = 10 for single mongos server (max pool = 60 for my 6 mongos cluster)? Or max connection pool = 10 for the whole cluster no matter how many mongos server we have?
max connection pool = 10 means that in the client pool there will be max 10 connections no matter hoe many server are part of your cluster.
Mongo Client
com.mongodb.client.MongoClient interface:
A client-side representation of a MongoDB cluster. Instances can represent either a standalone MongoDB instance, a replica set, or a sharded cluster. Instance of this class are responsible for maintaining an up-to-date state of the cluster, and possibly cache resources related to this, including background threads for monitoring, and connection pools.
MongoClient object is used to get access to the database, using the getDatebase() method and work with collections and documents in it.
From the documentation:
The MongoClient instance represents a pool of connections to the
database; you will only need one instance of class MongoClient even
with multiple threads.
IMPORTANT
Typically you only create one MongoClient instance for a
given MongoDB deployment (e.g. standalone, replica set, or a sharded
cluster) and use it across your application. However, if you do create
multiple instances:
All resource usage limits (e.g. max connections, etc.) apply per
MongoClient instance.
To dispose of an instance, call MongoClient.close() to clean up resources.
The following code creates a MongoDB client connection object with connection pooling to connect to a MongoDB instance.
MongoClient mongoClient = MongoClients.create();
MongoDatabase database = mongoClient.getDatabase("test");
MongoClients.create() static method creates a connection object specified by the default host (localhost) and port (27017). You can explicitly specify other settings with the MongoClientSettings which specifies various settings to control the behavior of a MongoClient.
MongoClient mongoClient = MongoClients.create(MongoClientSettings settings)
Connection Pool Settings:
The ConnectionPoolSettings object specifies all settings that relate to the pool of connections to a MongoDB server. The application creates this connection pool when the client object is created. This creating of connection pool is driver specific.
ConnectionPoolSettings.Builder is a builder for ConnectionPoolSettings has methods to specify the connection pool properties. E.g., maxSize(int maxSize): The maximum number of connections allowed. Default is 100. Other methods include, minSize, maxConnectionIdleTime, etc.
Code to instantiate a MongoClient with connection pool settings:
MongoClientSettings settings = MongoClientSettings.builder()
.applyToConnectionPoolSettings(builder ->
builder.maxSize(20).minSize(10)
.build();
MongoClient mongoClient = MongoClients.create(settings);
//...
// Verify the connection pool settings max size as
settings.getConnectionPoolSettings().getMaxSize()
Question: Is the connectionPoolSetting related to one mongos server?
or related to all mongos servers?
A client or application connects to the sharded cluster (includes all its shards) via the mongos router. The client program specifies the URL connection string and other options for the connection. In a sharded cluster, a client may connect thru a set of mongoss or a single mongos, or multiple clients can connect thru a single mongos, etc.,; it depends upon your application architecture.
If you are connecting via a single mongos, you can specify the mongos's host, port, user/password, etc., in the connection string. If it is a multiple mongos's, then multiple host/port values. Irrespective of the number of mongos's, the client program connects to the cluster via only one mongos.
The connection pool setting is for one mongos router only, as an application connects to one mongos irrespective of the number of mongoss specified in the connection string.
I want to create a "X" number of connections to mongodb on my application startup (i.e before my application starts taking traffic).
MongoDB Version: 4.0.11
Mongo Java Driver Version (maven): 3.4.1
I have tried setting the "minConnectionsPerHost" to the required number, but when i execute the code it barely open 1 or 2 connections. But, when i put load on my application the connection count is slowly going up to accommodate the traffic. I want to create those connections before my application starts taking traffic.
ServerAddress address = new ServerAddress("localhost", 27017);
List<ServerAddress> serverAddresses = Arrays.asList(address);
MongoCredential credential =
MongoCredential.createCredential("XXXX", "XXXX",
"XXXX".toCharArray());
List<MongoCredential> mongoCredentials =
Arrays.asList(credential);
MongoClientOptions clientOptions =
MongoClientOptions.builder().connectionsPerHost(100).
minConnectionsPerHost(50).build();
MongoClient mongoClient = new MongoClient(serverAddresses,
mongoCredentials, clientOptions);
Is there a way to achieve this using the mongo java driver?
You can set a minConnectionsPerHost() in the options builder, and then use a warmup script to create many connections. The connection pool will keep the minConnectionsPerHost connections alive without closing.
The warmup script can have a program which spawns 2*minConnectionsPerHost number of threads, which will connect and do may be a dummy read operation. This way connections will be opened, minimum connections will be kept alive.
This seems to be dirty solution :-) But might work!
Hey first time using mongo replica sets, and I've configured a set of 3 servers in Java. I'm trying to determine which secondary is being read from by my service (using secondary preferred). Does the mongo driver expose access to this info within Java?
As I'm struggling to find a reliable way to track it. I'm also aware once a connection is made to a secondary it is unlikely to switch to read from the other secondary unless there is failure.
You can use the getAdress method like below, see the documentation for more details.
MongoClient mongoClient = new MongoClient("localhost", 27017);
ServerAddress serverAdress = mongoClient.getAddress()
I am using Java to insert data into mongodb cluster.
Can I have more than 1 mongos instance so that I have a backup when 1 of my mongos is down?
Here is my java code to connect to mongos.
MongoClient mongoClient = new MongoClient("10.4.0.121",6001);
DB db = mongoClient.getDB("qbClientDB");
DBCollection collection = db.getCollection("clientInfo");
How can I specify my second mongos instance in my Java code? (If possible).
Thanks in advance.
The MongoClient docs say that you can, something similar to (the dummy addresses);
MongoClient mongoClient = new MongoClient(Arrays.asList(
new ServerAddress("10.4.0.121",6001),
new ServerAddress("10.4.0.122",6001),
new ServerAddress("10.4.0.123",6001)));
MongoClient will auto-detect whether the servers are a list of replica set members or a list of mongos servers.
public MongoClient(List<ServerAddress> seeds,
MongoClientOptions options)
//Creates a Mongo based on a list of replica set members or a list of mongos. It will find all members (the master will be used by default). If you pass in a single server in the list, the driver will still function as if it is a replica set. If you have a standalone server, use the Mongo(ServerAddress) constructor.
//If this is a list of mongos servers, it will pick the closest (lowest ping time) one to send all requests to, and automatically fail over to the next server if the closest is down.
MongoClient mongoClient = new MongoClient(Arrays.asList(
new ServerAddress("10.4.0.121",6001),
new ServerAddress("10.4.0.122",6001),
new ServerAddress("10.4.0.123",6001)));
Can I open several Mongo connections simultaneously from the same thread, or is it preferable to open just one connection and use it for all my calls?
Java MongoDB Driver maintains an internal connection pool, you should get a connection from MongoClient and then close it once you are done with it. MongoClient is thread safe, so you can use it easily in multi-threaded environment.
Quick sample code shown below.
MongoClient mongo = new MongoClient("localhost", 27017);
DB db = mongo.getDB("test");
DBCollection col = db.getCollection("users");
//Some operations
//close resources
mongo.close();
}
If you look at the documentation, you'll see that you'll be using a connection pool whether you want it or not, with a default maximum size of 100.
So to answer your question: use a single MongoClient across all threads, but bear in mind that this does not equate to a single MongoDB connection.