连接池

1057 发布于: 2021-04-01 读完约需 7 分钟

连接池概述

连接池是NESTElasticsearch.Net的一种内部机制,它主要负责注册和管理集群中的节点,以及协调NEST客户端如何向远程集群发送API调用。

尽管也是连接池,但NEST中的连接池并不像ADO.Net与数据库交互时熟悉的连接池。例如,NEST中的连接池不负责管理到Elasticsearch的TCP连接的底层池,这是由桌面CLR中的ServicePointManager处理的。

那么,NEST中的连接池主要负责什么呢?它负责管理可以建立连接的Elasticsearch集群中的节点,并且有一个与ConnectionSettings实例相关联的IConnectionPool实例。因此,建议在整个应用程序的生命周期中使用单个客户端和连接设置实例,单个连接池实例的生命周期也将与应用程序的生命周期进行绑定。

NEST提供了5种可用的连接池:

  • SingleNodeConnectionPool
  • CloudConnectionPool
  • StaticConnectionPool
  • SniffingConnectionPool
  • StickyConnectionPool

SingleNodeConnectionPool

SingleNodeConnectionPool 是5种连接池中最简单的一种,如果没有将连接池显式传递给ConnectionSettings构造函数,则使用默认连接池。它接收一个Uri参数并使用该Uri连接到Elasticsearch来进行所有调用。单节点连接池不会选择嗅探或ping行为,也不会标记节点的存活状态。

如果集群只包含单个节点,或者通过单个负载均衡器实例与集群交互,则可以使用单节点连接池。

var uri = new Uri("http://localhost:9201");
var pool = new SingleNodeConnectionPool(uri);
var client = new ElasticClient(new ConnectionSettings(pool));

当你使用ElasticClientUri作为惟一参数的构造器时,其他实例内部默认使用的即为一个SingleNodeConnectionPool连接池:

client = new ElasticClient(uri);

但是,建议还是显式地传递连接池的连接配置。

CloudConnectionPool

这是SingleNodeConnectionPool的专门的子类,主要是用来连接Elastic官方提供了Elasticsearch云服务(当然,你也可以搭建自己的Elasticsearch私有云服务),它接收Cloud Id凭证两个参数。在使用时,客户端还将为连接设置选择弹性云优化的默认值。

你可以从弹性云集群管理控制台获取集群的云Id。

一个云Id的形式应该是这样的:cluster_name:base_64_data,其中的base_64_data是云实例服务中的UUID,比如:

host_name$elasticsearch_uuid$kibana_uuid$apm_uuid

除此之外,只有host_nameelasticsearch_uuid始终可用。

可以使用凭据Cloud Id创建云连接池,如下:

var credentials = new BasicAuthenticationCredentials("username", "password"); 
var pool = new CloudConnectionPool(cloudId, credentials); 
var client = new ElasticClient(new ConnectionSettings(pool));

你也可以使用接收Cloud Id凭证参数的ElasticClient构造函数来创建云客户端实例,如:

client = new ElasticClient(cloudId, credentials);

StaticConnectionPool

如果你有一个小型Elasticsearch集群,并且不希望启用嗅探来查找集群拓扑,那么静态连接池非常有用。

给定一个Uri集合:

var uris = Enumerable.Range(9200, 5)
    .Select(port => new Uri($"http://localhost:{port}"));

然后使用这个集合来创建连接池:

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

嗅探连接池(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节点:

var nodes = uris.Select(u=>new Node(u));
pool = new SniffingConnectionPool(nodes);
client = new ElasticClient(new ConnectionSettings(pool));

使用节点的一个主要好处是,在传播时可以包含已知的节点角色,然后NEST可以使用这些角色来处理特定的API请求。

这种类型的池是硬连接的,可以选择重播(嗅探)和ping

StickyConnectionPool

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节点:

var nodes = uris.Select(u=>new Node(u));
pool = new StickyConnectionPool(nodes);
client = new ElasticClient(new ConnectionSettings(pool));

这种类型的池是硬连接的,可以选择不嗅探,但是支持ping

Sticky Sniffing Connection Pool

StickySniffingConnectionPool连接池返回第一个发出请求的活动节点,这样该节点在请求之间具有粘性。这个实现支持嗅探和排序,这样应用程序的每个实例都可以使用一个节点。例如,同一机架中的基于节点属性的节点。

给定一个Uri集合:

var uris = Enumerable.Range(9200, 5)
    .Select(port => new Uri($"http://localhost:{port}"));

嗅探排序的粘性池接受第二个参数,一个Func<Node, float>委托,它接受一个节点并返回一个权重,所有节点将按权重降序排序。下面的示例是对节点进行评分,有节点属性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));

版权声明:本作品系原创,版权归码友网所有,如未经许可,禁止任何形式转载,违者必究。

发表评论

登录用户才能发表评论, 请 登 录 或者 注册