Elasticsearch NettyTransport通訊機制
ES 當發起各種Action類的Request時, 在叢集環境中通常需要進行請求的轉發, 此時就會出現RPC通訊, 針對此RPC通訊ES 是透過NettyTransport類來完成轉發與接收功能的. 實際上就是基於Netty的一個通訊程式碼模組.
在Node啟動以及TransportClient初始化的過程中都會建立NettyTransport
Node節點啟動時
當節點Node啟動時會根據依賴注入獲取TransportService例項, 並呼叫其start方法,最終會轉向NettyTransport的doStart 方法, 進而建立Netty RPC的客戶端以及服務端物件, 透過MessageHandler來處理請求或者處理Response.
public Node start() { //... 省略 injector.getInstance(MappingUpdatedAction.class).setClient(client); injector.getInstance(IndicesService.class).start(); injector.getInstance(IndexingMemoryController.class).start(); injector.getInstance(IndicesClusterStateService.class).start(); injector.getInstance(IndicesTTLService.class).start(); injector.getInstance(SnapshotsService.class).start(); injector.getInstance(SnapshotShardsService.class).start(); injector.getInstance(RoutingService.class).start(); injector.getInstance(SearchService.class).start(); injector.getInstance(MonitorService.class).start(); injector.getInstance(RestController.class).start(); // TODO hack around circular dependencies problems injector.getInstance(GatewayAllocator.class).setReallocation(injector.getInstance(ClusterService.class), injector.getInstance(RoutingService.class)); injector.getInstance(ResourceWatcherService.class).start(); injector.getInstance(GatewayService.class).start(); // Start the transport service now so the publish address will be added to the local disco node in ClusterService TransportService transportService = injector.getInstance(TransportService.class); transportService.start(); injector.getInstance(ClusterService.class).start(); //... 省略 return this; }
轉而AbstractLifecycleComponent的start方法
public T start() { if (!lifecycle.canMoveToStarted()) { return (T) this; } for (LifecycleListener listener : listeners) { listener.beforeStart(); } doStart(); lifecycle.moveToStarted(); for (LifecycleListener listener : listeners) { listener.afterStart(); } return (T) this; }
doStart方法此處只分析NettyTransport的doStart方法(不分析LocalTransport的)
那段程式碼中有如下兩個比較關鍵:
clientBootstrap = createClientBootstrap(); // 啟動客戶端createServerBootstrap(name, mergedSettings); // 啟動Server端
看看客戶端的構造:
private ClientBootstrap createClientBootstrap() { if (blockingClient) { clientBootstrap = new ClientBootstrap(new OioClientSocketChannelFactory(Executors.newCachedThreadPool(daemonThreadFactory(settings, TRANSPORT_CLIENT_WORKER_THREAD_NAME_PREFIX)))); } else { int bossCount = settings.getAsInt("transport.netty.boss_count", 1); clientBootstrap = new ClientBootstrap(new NioClientSocketChannelFactory( Executors.newCachedThreadPool(daemonThreadFactory(settings, TRANSPORT_CLIENT_BOSS_THREAD_NAME_PREFIX)), bossCount, new NioWorkerPool(Executors.newCachedThreadPool(daemonThreadFactory(settings, TRANSPORT_CLIENT_WORKER_THREAD_NAME_PREFIX)), workerCount), new HashedWheelTimer(daemonThreadFactory(settings, "transport_client_timer")))); } clientBootstrap.setPipelineFactory(configureClientChannelPipelineFactory()); //... 省略 return clientBootstrap; }
上面程式碼一個注意的地方是clientBootstrap.setPipelineFactory(configureClientChannelPipelineFactory());
public ChannelPipelineFactory configureClientChannelPipelineFactory() { return new ClientChannelPipelineFactory(this); }
protected static class ClientChannelPipelineFactory implements ChannelPipelineFactory { protected final NettyTransport nettyTransport; public ClientChannelPipelineFactory(NettyTransport nettyTransport) { this.nettyTransport = nettyTransport; } @Override public ChannelPipeline getPipeline() throws Exception { ChannelPipeline channelPipeline = Channels.pipeline(); SizeHeaderFrameDecoder sizeHeader = new SizeHeaderFrameDecoder(); if (nettyTransport.maxCumulationBufferCapacity != null) { if (nettyTransport.maxCumulationBufferCapacity.bytes() > Integer.MAX_VALUE) { sizeHeader.setMaxCumulationBufferCapacity(Integer.MAX_VALUE); } else { sizeHeader.setMaxCumulationBufferCapacity((int) nettyTransport.maxCumulationBufferCapacity.bytes()); } } if (nettyTransport.maxCompositeBufferComponents != -1) { sizeHeader.setMaxCumulationBufferComponents(nettyTransport.maxCompositeBufferComponents); } channelPipeline.addLast("size", sizeHeader); // using a dot as a prefix means, this cannot come from any settings parsed channelPipeline.addLast("dispatcher", new MessageChannelHandler(nettyTransport, nettyTransport.logger, ".client")); return channelPipeline; } }
上面的程式碼中channelPipeline.addLast("dispatcher", new MessageChannelHandler(nettyTransport, nettyTransport.logger, ".client"));指定了使用MessageChannelHandler來進行接收處理請求或者Response
createServerBootstrap(name, mergedSettings); // 啟動Server端 基本和createClientBootstrap()流程相似, 最終都是透過MessageChannelHandler來進行接收處理請求或者Response.
建立TransportClient時
當呼叫build方法時會根據依賴注入獲取TransportService例項, 並呼叫其start方法,最終會轉向NettyTransport的doStart 方法, 進而建立Netty RPC的客戶端以及服務端物件, 透過MessageHandler來處理請求或者處理Response.
它的具體流程和上面基本一致.
整體的結構圖如圖所示
image.png
透過這樣的方式, 當Client發起一個請求, 比如先發給協調器, 協調器可能需要透過NettyTranport(也可能是LocalTransport, 看具體情況)轉發到其他的Node, 最終會透過MessageChannelHandler進行處理Request以及Response
作者:kason_zhang
連結:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/1762/viewspace-2816613/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Binder通訊機制
- Binder通訊機制與IPC通訊.md
- 通訊機制 synchronous communication
- Linux程式通訊機制Linux
- HTTPS的安全通訊機制HTTP
- ReactNative原始碼篇:通訊機制React原始碼
- Kubernetes的容器網路通訊機制
- Linux 程式間通訊的六種機制Linux
- 執行緒間通訊_等待/通知機制執行緒
- React Native原理之跨端通訊機制React Native跨端
- 一張圖進階 RocketMQ - 通訊機制MQ
- Elasticsearch 模組 - Shard Allocation 機制Elasticsearch
- WebRTC 及點對點網路通訊機制Web
- Android 系統原始碼-2:Binder 通訊機制Android原始碼
- ros的幾種通訊機制及程式碼ROS
- Java 執行緒間通訊 —— 等待 / 通知機制Java執行緒
- 螞蟻金服通訊框架 SOFABolt 解析 | 超時控制機制及心跳機制框架
- PHP-FPM 與 Nginx 的通訊機制總結PHPNginx
- 深入探討程式間通訊的重要性:理解不同的通訊機制(下)
- 深入探討程式間通訊的重要性:理解不同的通訊機制(上)
- 聊聊 Elasticsearch 中的任務管理機制Elasticsearch
- ElasticSearch 文件(document)內部機制詳解Elasticsearch
- Linux環境程式設計程式間通訊機制理解Linux程式設計
- android 非同步通訊機制Handler的分析與運用Android非同步
- [原始碼解析] TensorFlow 分散式環境(8) --- 通訊機制原始碼分散式
- 螞蟻金服通訊框架SOFABolt解析|編解碼機制框架
- 深入探討微服務架構中的同步通訊機制微服務架構
- 高頻考點,六大程式通訊機制總結
- linux 訊號機制Linux
- 螞蟻金服通訊框架SOFABolt解析|序列化機制(Serializer)框架
- 螞蟻金服通訊框架SOFABolt解析 |序列化機制(Serializer)框架
- Dubbo原始碼分析(六)Dubbo通訊的編碼解碼機制原始碼
- 通俗易懂剖析Go Channel:理解併發通訊的核心機制Go
- Python 併發程式設計(四):詳解 Python 執行緒訊息通訊機制Python程式設計執行緒
- 一種go協程間記憶體零拷貝的訊息通訊機制Go記憶體
- 理解 Android 訊息機制Android
- Android訊息機制HandlerAndroid
- android訊息機制—HandlerAndroid