Connection pools
editConnection pools
editConnection pooling is the internal mechanism that takes care of registering what nodes there are in the cluster and which NEST can use to issue client calls on.
Despite the name, a connection pool in NEST is not like connection pooling that you may be familiar with from interacting with a database using ADO.Net; for example, a connection pool in NEST is not responsible for managing an underlying pool of TCP connections to Elasticsearch, this is handled by the ServicePointManager in Desktop CLR.
So, what is a connection pool in NEST responsible for? It is responsible for managing the nodes in an Elasticsearch
cluster to which a connection can be made and there is one instance of an IConnectionPool
associated with an
instance of ConnectionSettings
. Since a single client and connection settings instance is recommended for the
life of the application, the lifetime of a single connection pool instance will also be bound to the lifetime
of the application.
There are five types of connection pool
SingleNodeConnectionPool
editThe simplest of all connection pools and the default if no connection pool is explicitly passed to the ConnectionSettings
constructor.
It takes a single Uri
and uses that to connect to Elasticsearch for all the calls. Single node connection pool doesn’t opt in to
sniffing or pinging behavior and will never mark nodes dead or alive. The one Uri
it holds is always ready to go.
Single node connection pool is the pool to use if your cluster contains only a single node or you are interacting with your cluster through a single load balancer instance.
var uri = new Uri("http://localhost:9201"); var pool = new SingleNodeConnectionPool(uri); var client = new ElasticClient(new ConnectionSettings(pool));
This type of pool is hardwired to opt out of reseeding (sniffing) as well as pinging
When you use the low ceremony ElasticClient
constructor that takes a single Uri
,
internally a SingleNodeConnectionPool
is used
client = new ElasticClient(uri);
However we encourage you to pass connection settings explicitly.
CloudConnectionPool
editA specialized subclass of SingleNodeConnectionPool
that accepts a Cloud Id and credentials.
When used the client will also pick Elastic Cloud optimized defaults for the connection settings.
A Cloud Id for your cluster can be fetched from your Elastic Cloud cluster administration console.
A Cloud Id should be in the form of cluster_name:base_64_data
where base_64_data
are the UUIDs for the services in this cloud instance e.g
host_name$elasticsearch_uuid$kibana_uuid$apm_uuid
Out of these, only host_name
and elasticsearch_uuid
are always available.
A cloud connection pool can be created using credentials and a cloudId
var credentials = new BasicAuthenticationCredentials("username", "password"); var pool = new CloudConnectionPool(cloudId, credentials); var client = new ElasticClient(new ConnectionSettings(pool));
a username and password that can access Elasticsearch service on Elastic Cloud |
|
|
This type of pool, like its parent the SingleNodeConnectionPool
, is hardwired to opt out of
reseeding (sniffing) as well as pinging.
You can also directly create a cloud enabled connection using the ElasticClient
's constructor
client = new ElasticClient(cloudId, credentials);
StaticConnectionPool
editThe static connection pool is great if you have a known small sized cluster and do no want to enable sniffing to find out the cluster topology.
Given a collection of Uri
var uris = Enumerable.Range(9200, 5) .Select(port => new Uri($"http://localhost:{port}"));
a connection pool can be seeded with this collection
var pool = new StaticConnectionPool(uris); var client = new ElasticClient(new ConnectionSettings(pool));
Or using an enumerable of Node
var nodes = uris.Select(u => new Node(u)); pool = new StaticConnectionPool(nodes); client = new ElasticClient(new ConnectionSettings(pool));
This type of pool is hardwired to opt out of reseeding (sniffing) but supports pinging when enabled.
SniffingConnectionPool
editA pool derived from StaticConnectionPool
, a sniffing connection pool allows itself to be reseeded at run time.
It comes with the very minor overhead of a ReaderWriterLockSlim
to ensure thread safety.
Given a collection of Uri
var uris = Enumerable.Range(9200, 5) .Select(port => new Uri($"http://localhost:{port}"));
a connection pool can be seeded using an enumerable of Uri
var pool = new SniffingConnectionPool(uris); var client = new ElasticClient(new ConnectionSettings(pool));
Or using an enumerable of Node
. A major benefit in using nodes is that you can include
known node roles when seeding, which NEST can then use to favour particular API requests. For example,
sniffing on master eligible nodes first, and take master only nodes out of rotation for issuing client calls on.
var nodes = uris.Select(u=>new Node(u)); pool = new SniffingConnectionPool(nodes); client = new ElasticClient(new ConnectionSettings(pool));
This type of pool is hardwired to opt in to reseeding (sniffing), and pinging
StickyConnectionPool
editA type of connection pool that returns the first live node to issue a request against, such that the node is sticky between requests.
It uses System.Threading.Interlocked
to keep an indexer to the last live node in a thread safe manner.
Given a collection of Uri
var uris = Enumerable.Range(9200, 5) .Select(port => new Uri($"http://localhost:{port}"));
a connection pool can be seeded using an enumerable of Uri
var pool = new StickyConnectionPool(uris); var client = new ElasticClient(new ConnectionSettings(pool));
Or using an enumerable of Node
, similar to SniffingConnectionPool
var nodes = uris.Select(u=>new Node(u)); pool = new StickyConnectionPool(nodes); client = new ElasticClient(new ConnectionSettings(pool));
This type of pool is hardwired to opt out of reseeding (sniffing), but does support pinging.
Sticky Sniffing Connection Pool
editA type of connection pool that returns the first live node to issue a request against, such that the node is sticky between requests. This implementation supports sniffing and sorting so that each instance of your application can favour a node. For example, a node in the same rack, based on node attributes.
Given a collection of Uri
var uris = Enumerable.Range(9200, 5) .Select(port => new Uri($"http://localhost:{port}"));
a sniffing sorted sticky pool takes a second parameter, a delegate of Func<Node, float>
, that takes a Node and returns a weight.
Nodes will be sorted in descending order by weight. In the following example, nodes are scored so that client nodes
in rack_id rack_one
score the highest
var pool = new StickySniffingConnectionPool(uris, node => { var weight = 0f; if (node.ClientNode) weight += 10; if (node.Settings.TryGetValue("node.attr.rack_id", out var rackId) && rackId.ToString() == "rack_one") weight += 10; return weight; }); var client = new ElasticClient(new ConnectionSettings(pool));