elasticsearch源码之Transport
es使用netty来实现client和server,netty的启动在NettyTransport.java中,在此类中使用ChannelPipeline初始化了ClientBootstrap和ServerBootstrap,关于channelpipline这边不再多介绍,是netty中的一项功能。es的每个节点既是一个client也是一个server,先看一下client端的实现,client的主要功能是sendRequest和handle response。
client
client的主要功能是发送请求,并处理response,一般来说这是一个阻塞的过程,es的发送请求和处理response是分开的。
发送数据
es的各个模块在需要发请求是通过调用TransportService中的sendRequest方法。
public <T extends TransportResponse> void sendRequest(final DiscoveryNode node, final String action, final TransportRequest request,
final TransportRequestOptions options, TransportResponseHandler<T> handler) throws TransportException {
if (node == null) {
throw new ElasticsearchIllegalStateException("can't send request to a null node");
}
final long requestId = newRequestId(); //通过原子类生成一个唯一的requestID
TimeoutHandler timeoutHandler = null;
try {
if (options.timeout() != null) {
timeoutHandler = new TimeoutHandler(requestId);
timeoutHandler.future = threadPool.schedule(options.timeout(), ThreadPool.Names.GENERIC, timeoutHandler);
}
clientHandlers.put(requestId, new RequestHolder<T>(handler, node, action, timeoutHandler));
transport.sendRequest(node, requestId, action, request, options);
} catch (final Throwable e) {
final RequestHolder holderToNotify = clientHandlers.remove(requestId);
if (timeoutHandler != null) {
timeoutHandler.future.cancel(false);
}
if (holderToNotify != null) {
final SendRequestTransportException sendRequestException = new SendRequestTransportException(node, action, e);
threadPool.executor(ThreadPool.Names.GENERIC).execute(new Runnable() {
@Override
public void run() {
holderToNotify.handler().handleException(sendRequestException);
}
});
}
if (throwConnectException) {
if (e instanceof ConnectTransportException) {
throw (ConnectTransportException) e;
}
}
}
DiscoveryNode是节点对象,action代表此请求的action类型,TransportRequest存储的是请求的数据,TransportRequestOptions代表请求选项,包括请求的类型(用于后边请求时使用不同的连接),timeout等信息,TransportResponseHandler是请求返回的response处理对象。
1.先使用AtomicLong生成了一个requestId
2.判断是否有超时设置,若是有的话,启动一个定时任务,使用timeoutHandler 处理这个requestId。
3.将requestId 和RequestHolder对象的映射关系存入到clientHandlers中(用于处理response),RequestHolder对象将请求返回的response处理对象,action,timeoutHandler,node进行封装。
4,最后调用Transport中的sendRequest方法,这里的transport实际上就是NettyT