一、基本介绍
1.1概念介绍
transport模块是es通信的基础模块,在elasticsearch中用的很广泛,比如集群node之间的通信、数据的传输、transport client方式的数据发送等等,只要数和通信、数据传输相关的都离不开transport模块的作用。
transport模块分为LocalTransport和NettyTransport两种,在TransportModule中注册中可以通过node是local还是network的来判别使用哪一种transport,可以通过配置node.mode
来决定,bind逻辑如下:
默认而且通常我们使用的实现类是NettyTransport,描述信息如下:
NettyTransport分为四种类型的连接,分别是:
- recovery:做数据恢复recovery,默认个数2个;
- bulk:用于bulk请求,默认个数3个;
- med/reg:典型的搜索和单doc索引,默认个数6个;
- high:如集群state的发送等,默认个数1个;
- ping:就是node之间的ping咯。默认个数1个;
其中recovery和bulk之前版本是同一个的,叫做low,表示大数据量的传输,它们可能会导致通常的请求(如search或是单数据索引)耗时加长;
1.2配置信息
1.2.1workerCount
workerCount表示transport的总共的worker数目,由transport.netty.worker_count
来配置,默认值是32和Runtime.getRuntime().availableProcessors()中的最小值,也就是不能超过32,为什么会有这个限制呢?是因为在elasticsearch的github上有人提了个issues/3478,当使用core很多的机器的时候(比如48core),会创建太多的内存从而导致OOM,所以设置了32的上限来避免太多线程给系统产生压力。
创建逻辑
创建serverBootstap
创建clientBootstap
1.2.2connetion number
1.1中介绍的各种连接数初始化
1.3.2defaultReceiverPredictor
Netty是nio的,在Netty中通过ReceiveBufferSizePredictor根据上次消息的大小来决定预测本次消息所需的缓存大小。
从channel读取数据到缓存到,并向上行流通知消息接收事件。默认值计算逻辑:
JvmInfo.jvmInfo().getMem().getDirectMemoryMax()
,最终调用的就是jdk中sun.misc.VM
类里面的directMemory ,可以通过 -XX:MaxDirectMemorySize来配置的,默认是64M.
二、创建连接
2.1启动服务
因为NettyTransport继承了AbstractLifecycleComponent,实现了doStart()方法。在node、transportclient启动的时候调用了
最终调用了doStart()方法,在doStart中会根据配置启动一个client和一个server,分别是ClientBootstrap
和ServerBootstrap
(都是Netty中的),因为节点之间要相互通信的,所以client和sever都要启动。并分别注册各自的PipelineFactory,在PipelineFactory中创建各自的channelPipeline,其中注册了消息处理的方式。
客户端
服务端
2.2连接节点
在启动Discovery服务后,会发现新节点,发现之后开始进行连接工作。在UnicastZenPing中会调用transportService.connectToNodeLight(finalNodeToSend)进行连接。
实质就是创建Netty中的Channel,一个连接就是第一个Channel,根据之前所说的会有多个类型的连接会创建:
nodeChannels = new NodeChannels(new Channel[connectionsPerNodeRecovery],
new Channel[connectionsPerNodeBulk], new Channel[connectionsPerNodeReg],
new Channel[connectionsPerNodeState], new Channel[connectionsPerNodePing]);
上面连接创建完毕,供后续数据传输使用。
三、发送数据
3.1获取channel
sendRequest方法会传入一个参数options
,是一个TransportRequestOptions
的实例,包含三个属性:timeout(超时时间)、compress(是否压缩)、type(发送的类型,即上面说的五个之一)。
根据需要发送数据的节点和发送的类型(上面五大类型)获得到对应的channel
3.1数据写入
之后数据该压缩的压缩(压缩方法在CompressorFactory中实现),并写入version和action;
写入request信息,通过ChannelBuffers创建出buffer;
3.3数据发送
最后通过Netty中的targetChannel.write(buffer),
将数据发送。
四、接收数据
4.1处理类注册
参照2.1启动服务中的channelPipeline注册,统一的handler为MessageChannelHandler,负责消息接受及处理逻辑,在其他模块中会对不同的消息(Action)注册对应的处理程序(handler)。
4.2消息处理
在对收到的内容进行解析的过程中获取到action,找到对应的handler进行处理;消息处理则需要messageReceived,里面会有对于request和response分别有相应的handler来处理:handleRequest、handleResponse。
具体使用方式可以参照elasticsearch源码分析之服务端(四)