连接池是一种内部机制,用于注册集群中的哪些节点以及NEST可以用来发出客户端调用的内部机制。
IMPORTANT
尽管有名称,但NEST中的连接池与使用ADO.Net与数据库进行交互时可能不熟悉的连接池不同。例如,NEST中的连接池不负责管理与Elasticsearch的TCP连接的基础池,这由Desktop CLR中的ServicePointManager处理。
那么,NEST中的连接池负责什么呢?它负责管理Elasticsearch集群中可以建立连接的节点,并且有一个IConnectionPool实例与ConnectionSettings实例相关联。由于建议在应用程序的生存期内使用单个客户端和连接设置实例,因此单个连接池实例的生存期也将与应用程序的生存期绑定。
连接池有五种类型:
SingleNodeConnectionPool
所有连接池中最简单的一个,如果没有任何连接池显式传递给ConnectionSettings构造函数,则为默认值。它需要一个Uri,并使用它来连接到所有调用的Elasticsearch。单节点连接池不会选择嗅探或ping行为,并且永远不会将节点标记为死亡或活动。它拥有的一个Uri随时可以使用。 如果群集仅包含单个节点,或者您通过单个负载均衡器实例与群集进行交互,则使用单节点连接池。
var uri = new Uri("http://localhost:9201");
var pool = new SingleNodeConnectionPool(uri);
var client = new ElasticClient(new ConnectionSettings(pool));
|
这种类型的池硬连线选择退出重新播种(嗅探)和查验 当您使用采用单个Uri的低级仪式ElasticClient构造函数时,在内部使用SingleNodeConnectionPool
client = new ElasticClient(uri);
|
但是,我们建议您显式传递连接设置。
CloudConnectionPool
SingleNodeConnectionPool的专用子类,它接受云ID和凭据。使用后,客户端还将为连接设置选择Elastic Cloud优化的默认值。
可以从您的Elastic Cloud集群管理控制台中获取集群的Cloud ID。
云ID的格式应为cluster_name:base_64_data,其中base_64_data是此云实例中服务的UUID,例如
host_name$elasticsearch_uuid$kibana_uuid$apm_uuid
其中,仅host_name和elasticsearch_uuid始终可用。
可以使用凭据和cloudId创建云连接池
var credentials = new BasicAuthenticationCredentials("username", "password"); ①
var pool = new CloudConnectionPool(cloudId, credentials); ②
var client = new ElasticClient(new ConnectionSettings(pool));
|
① 可以访问Elastic Cloud上的Elasticsearch服务的用户名和密码
② cloudId是可以从Elastic Cloud Web控制台检索的值
这种类型的池(与其父级SingleNodeConnectionPool一样)被硬连线以选择不进行重新播种(嗅探)和ping。
您还可以使用ElasticClient的构造函数直接创建启用了云的连接
client = new ElasticClient(cloudId, credentials);
|
StaticConnectionPool(静态连接池)
如果您有一个已知的小型集群,并且不想启用嗅探功能来发现集群拓扑,则静态连接池非常有用。
给定一个集合 Uri
var uris = Enumerable.Range(9200, 5)
.Select(port => new Uri($"http://localhost:{port}"));
|
可以使用Uri枚举为连接池设定种子
var pool = new StaticConnectionPool(uris);
var client = new ElasticClient(new ConnectionSettings(pool));
|
或使用可枚举的Node
var nodes = uris.Select(u => new Node(u));
pool = new StaticConnectionPool(nodes);
client = new ElasticClient(new ConnectionSettings(pool));
|
这种类型的池被硬连线选择退出重新播种(嗅探),但在启用后支持ping。
SniffingConnectionPool
一个从StaticConnectionPool派生的池,一个嗅探连接池允许其在运行时重新播种。它带有ReaderWriterLockSlim的很小开销,以确保线程安全。
给定一个集合 Uri
var uris = Enumerable.Range(9200, 5)
.Select(port => new Uri($"http://localhost:{port}"));
|
可以使用Uri枚举为连接池设定种子
var pool = new SniffingConnectionPool(uris);
var client = new ElasticClient(new ConnectionSettings(pool));
|
或使用可枚举的Node。使用节点的主要好处是可以在播种时包括已知的节点角色,然后NEST可以使用这些角色来支持特定的API请求。例如,先在符合资格的主节点上进行嗅探,然后将仅主节点的节点从旋转中移出,以发出客户端呼叫。
var nodes = uris.Select(u=>new Node(u));
pool = new SniffingConnectionPool(nodes);
client = new ElasticClient(new ConnectionSettings(pool));
|
这种类型的池被硬连线以选择重新播种(嗅探)和ping
StickyConnectionPool
一种连接池,它返回要向其发出请求的第一个活动节点,以使该节点在请求之间处于粘滞状态。它使用System.Threading.Interlocked以线程安全的方式将索引器保留到最后一个活动节点。
给定一个集合 Uri
var uris = Enumerable.Range(9200, 5)
.Select(port => new Uri($"http://localhost:{port}"));
|
可以使用Uri枚举为连接池设定种子
var pool = new StickyConnectionPool(uris);
var client = new ElasticClient(new ConnectionSettings(pool));
|
或使用可枚举的Node,类似于SniffingConnectionPool
var nodes = uris.Select(u=>new Node(u));
pool = new StickyConnectionPool(nodes);
client = new ElasticClient(new ConnectionSettings(pool));
|
这种类型的池被硬连线选择退出重新播种(嗅探),但确实支持ping操作。
Sticky Sniffing Connection Pooledit
一种连接池,它返回要向其发出请求的第一个活动节点,以使该节点在请求之间处于粘滞状态。此实现支持嗅探和排序,以便您的应用程序的每个实例都可以支持一个节点。例如,基于节点属性,同一机架中的节点。
给定一个集合 Uri
var uris = Enumerable.Range(9200, 5)
.Select(port => new Uri($"http://localhost:{port}"));
|
嗅探排序的粘性池采用第二个参数,即Func <Node,float>的委托,该参数采用Node并返回权重。节点将按权重降序排列。在以下示例中,对节点进行评分,以使rack_id rack_one中的客户端节点得分最高
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));
|