Feature: Enable Multiple Connections #346
Closed
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Driver can now open and handle multiple connections to MongoDB.
Description
We have changed the
Cluster.swift
,Connection.swift
, Connection+Execute.swift
and IsMaster.swift
in order to utilize MongoKitten's already existing multiple connections set up which wasn't fully implemented.IsMaster
:isHandshake: Bool
. It's used to determine whether the connection is doing a handshake and thus decide whether it can be reused.init
with a default value offalse
.
Connection
:isInUse
boolean flag, as a way to know if the connection is busy or available.timeout
variable from ConnectionSettings
.doHandshake
now uses new constructor of IsMaster
class.
Connection+Execute
:command: Document
argument on functionexecute
now includes theisHandshake
flag (it will be cleaned up after).execute
now checks if it's a handshake connection.false
(it isn't a handshake connection), the connection is marked as not available (connection'sisInUse
variable is set to true).true
(it is a handshake connection), the connection will remain available to use by another query.command
variable. (We didn't want to changeexecute
's signature as to not provoke any unexpected behaviour).execute
sets the connection's completion (result.whenComplete
) to set the connection'sisInUse
flag back tofalse
respecting theisHandshake
condition (if it was a handshake, it won't set the flag totrue
as it didn't set it tofalse
before).Cluster
:poolBalancerCounter: NIOAtomic<Int64>
- Used to distribute queries throughout the connections in the pool.poolRequestedCounter: NIOAtomic<Int8>
- Used to control how many connections were requested to be created and are still alive in order to create connections respecting theConnectionSettings
'smaximumNumberOfConnections
variable.pool: [PooledConnection]
variable we configured it'sdidSet
property observer to subtract frompoolRequestedCounter
whenpool.count
is smaller thanoldValue
(when a connection is removed from the pool, the counter updates).findMatchingConnection
now has a new logic:poolRequestedCounter
) is less than the settings'maximumNumberOfConnections
:- If there is an available connection, it will return it.
- If there is no available connection, it will return
nil
and incrementpoolRequestedCounter
.poolBalancerCounter
to determine what was the last connection to receive a query and then try the next one)._getConnection
changed to create connections for hosts that have already been created (currently we resort to first creating connections to all undiscovered hosts and if there are none, we use the first that is stored in thediscoveredHosts
list. Ideally, it should be a queue, but that's out of scope for these changes).Motivation and Context
We are building an app and needed an API. We have some experience with other API frameworks in other languages (SpringBoot with Java and .NET with C#) and were able to identify some bottlenecks with our API when connecting to MongoDB using Fluent (which has the
Fluent-Mongo-Driver
that depends on MongoKitten).The bottleneck:
Our API was slowing down waiting for queries to complete and when we looked the performance tab in Mongo Compass it showed that there was only one connection being made. We searched for this issue and found people saying to increase the
maximumNumberOfConnections
when creating Fluent'sDatabaseConfigurationFactory
and it didn't increased our connections.We started to read all Fluent's abstractions and it seemed ok, it was passing the "request" for new connections all the way down.
After a while we arrived on MongoKitten and read through everything until we understood that MongoKitten had everything set up to handle multiple connections, but it wasn't being used for some reason. We changed a few pieces of code (only 4 files) and now we are creating connections as needed. Our problem was solved and we hope we can help other people who may face this problem as well.
How Has This Been Tested?
We validated the increase on throughput capability:
We tested edge cases:
Checklist:
• [ ] If applicable, I have updated the documentation accordingly.
• [ ] If applicable, I have added tests to cover my changes.
Contributors:
Myself
Gabriel M
Our thanks
Rafael and Marina who gave us many ideas and helped us with hard concepts we were unfamiliar with.