elasticsearch怎么实现客户端负载均衡

60次阅读
没有评论

共计 3404 个字符,预计需要花费 9 分钟才能阅读完成。

本篇内容介绍了“elasticsearch 怎么实现客户端负载均衡”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让丸趣 TV 小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

  客户端负载均衡技术是,客户端维护一组服务器引用,每次客户端请求的时候,会根据负载均衡算法选中一个节点,发送请求。常用的负载算法有 Random,Round robin,Hash,StaticWeighted 等。ES 的客户端负载使用了 Round robin 算法。(另外 Hash 一致性算法还会在另一地方遇见的) 一个 Count 请求的整个客户端模块的调用流程是

简化的调用流程

client 提供了客户端的操作接口,比如 count()

nodesService 的 execute() 随机一个节点出来

Proxy 代理通过 transportService 发送请求

一些初始化的事情

我们先看下创建客户端的代码,这里配置了几个配置项

Settings settings = ImmutableSettings.settingsBuilder()
 .put(cluster.name ,  myClusterName)
 .put(client.transport.sniff , true).build();
client=new TransportClient(settings)
 .addTransportAddress(new InetSocketTransportAddress( localhost ,9300));

谁会在乎这些配置项呢,就是 TransportClientNodesService 类。它负责着嗅探,维护集群节点列表。选举节点。它的构造方法里做了一些初始化工作

 this.nodesSamplerInterval = componentSettings.getAsTime(nodes_sampler_interval , timeValueSeconds(5));
 this.pingTimeout = componentSettings.getAsTime(ping_timeout , timeValueSeconds(5)).millis();
 this.ignoreClusterName = componentSettings.getAsBoolean(ignore_cluster_name , false);
 //.....
 if (componentSettings.getAsBoolean( sniff , false)) { this.nodesSampler = new SniffNodesSampler();
 } else { this.nodesSampler = new SimpleNodeSampler();
 }
 this.nodesSamplerFuture = threadPool.schedule(nodesSamplerInterval, ThreadPool.Names.GENERIC, new ScheduledNodeSampler());

nodes_sampler_interval  嗅探集群节点的间隔,默认 5 秒

pingTimeout Ping 节点的超时时间,默认是 5 秒

ignoreClusterName  忽略集群名称,集群验证的时候

sniff  是否开启集群嗅探

另外 TransportClientNodesService 维护着 2 个列表,集群节点列表 nodes 和监听列表 listedNodes。其中监听列表就是通过 TransportClient.addTransportAddress() 增加的节点列表。

嗅探集群节点

 interface NodeSampler { void sample();
 }

NodeSampler 接口很简单,只有一个 sample() 方法,它的实现类有 2 个 SniffNodesSampler 和 SimpleNodeSampler,我们在初始化里已经看到了,如果 sniff 配置项是 true 的话使用 SniffNodesSampler 类。它们 2 个的实现逻辑是

SimpleNodeSampler 

循环 listedNodes 列表里的每一个节点

没有连接就连接到这个节点

发送 cluster/nodes/info 请求获取节点的集群名称,需要的话,做集群名验证。

增加到 nodes 节点列表

SniffNodesSampler

创建一个 listedNodes 和 nodes 去重后的列表 nodesToPing

循环 nodesToPing 里的每一个节点

没有连接就连接到这个节点,如果是 nodes 列表的就正常连接,listedNode 列表的建立个轻连接就好了

发送 cluster/state 请求获取节点的状态,这里会有集群所有的数据节点 dataNodes

再次确认下已经和所有节点建立连接

增加到 nodes 节点列表

       

  我们可以发现 SimpleNodeSampler 最终的节点列表还是 listedNodes,如果我们建立客户端的时候,只添加了一个 localhost,那它所有的请求都会发送到 localhost。只有 SniffNodesSampler 才去探测集群的所有节点。也就是 SimpleNodeSampler 的意图是让集群中的某些个节点,专门用于接受用户请求。SniffNodesSampler 的话,所有节点都会参与负载。

class ScheduledNodeSampler implements Runnable {
 @Override
 public void run() {
 try { nodesSampler.sample();
 if (!closed) { nodesSamplerFuture = threadPool.schedule(nodesSamplerInterval, ThreadPool.Names.GENERIC, this);
 }
 } catch (Exception e) { logger.warn( failed to sample , e);
 }
 }
}

ScheduledNodeSampler 线程启动后,Sampler 就开始忙碌起来了。

选举节点

有了集群节点列表后 execute() 方法就可以通过轮询调度算法 Round robin,选举节点了。算法的特点是实现起来简单优雅,请求会被均衡的发送到各个节点上。

public  T  T execute(NodeCallback T  callback) throws ElasticSearchException {
 ImmutableList DiscoveryNode  nodes = this.nodes;
 if (nodes.isEmpty()) { throw new NoNodeAvailableException();
 }
 int index = randomNodeGenerator.incrementAndGet();
 if (index   0) {
 index = 0;
 randomNodeGenerator.set(0);
 }
 for (int i = 0; i   nodes.size(); i++) { DiscoveryNode node = nodes.get((index + i) % nodes.size());
 try { return callback.doWithNode(node);
 } catch (ElasticSearchException e) { if (!(e.unwrapCause() instanceof ConnectTransportException)) {
 throw e;
 }
 }
 }
 throw new NoNodeAvailableException();}

关键是这一行代码,说那么多话,其实,我只是了为了这么,一行代码啊?

DiscoveryNode node = nodes.get((index + i) % nodes.size());

“elasticsearch 怎么实现客户端负载均衡”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注丸趣 TV 网站,丸趣 TV 小编将为大家输出更多高质量的实用文章!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-16发表,共计3404字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)