您好,登錄后才能下訂單哦!
本篇內容介紹了“elasticsearch怎么實現客戶端負載均衡”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
客戶端負載均衡技術是,客戶端維護一組服務器引用,每次客戶端請求的時候,會根據負載均衡算法選中一個節點,發送請求。常用的負載算法有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怎么實現客戶端負載均衡”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。