1 ActionModule
在了解ES源代码增删改查之前, 首先要了解一下TransportClient build时的一个关键Action的注入------ActionModule
在ActionModule的configure函数中, 会注册各种各样的Action 并绑定到具体的Handler(实际上就是TransportRequestHandler), 这个Handler很关键
registerAction(NodesInfoAction.INSTANCE, TransportNodesInfoAction.class); registerAction(NodesStatsAction.INSTANCE, TransportNodesStatsAction.class); registerAction(NodesHotThreadsAction.INSTANCE, TransportNodesHotThreadsAction.class); registerAction(ListTasksAction.INSTANCE, TransportListTasksAction.class); registerAction(CancelTasksAction.INSTANCE, TransportCancelTasksAction.class); registerAction(ClusterStatsAction.INSTANCE, TransportClusterStatsAction.class); registerAction(ClusterStateAction.INSTANCE, TransportClusterStateAction.class); registerAction(ClusterHealthAction.INSTANCE, TransportClusterHealthAction.class); registerAction(ClusterUpdateSettingsAction.INSTANCE, TransportClusterUpdateSettingsAction.class); registerAction(ClusterRerouteAction.INSTANCE, TransportClusterRerouteAction.class); registerAction(ClusterSearchShardsAction.INSTANCE, TransportClusterSearchShardsAction.class); registerAction(PendingClusterTasksAction.INSTANCE, TransportPendingClusterTasksAction.class); registerAction(PutRepositoryAction.INSTANCE, TransportPutRepositoryAction.class); registerAction(GetRepositoriesAction.INSTANCE, TransportGetRepositoriesAction.class); registerAction(DeleteRepositoryAction.INSTANCE, TransportDeleteRepositoryAction.class); registerAction(VerifyRepositoryAction.INSTANCE, TransportVerifyRepositoryAction.class); registerAction(GetSnapshotsAction.INSTANCE, TransportGetSnapshotsAction.class); registerAction(DeleteSnapshotAction.INSTANCE, TransportDeleteSnapshotAction.class); registerAction(CreateSnapshotAction.INSTANCE, TransportCreateSnapshotAction.class); registerAction(RestoreSnapshotAction.INSTANCE, TransportRestoreSnapshotAction.class); registerAction(SnapshotsStatusAction.INSTANCE, TransportSnapshotsStatusAction.class); registerAction(IndicesStatsAction.INSTANCE, TransportIndicesStatsAction.class); registerAction(IndicesSegmentsAction.INSTANCE, TransportIndicesSegmentsAction.class); registerAction(IndicesShardStoresAction.INSTANCE, TransportIndicesShardStoresAction.class); registerAction(CreateIndexAction.INSTANCE, TransportCreateIndexAction.class); registerAction(DeleteIndexAction.INSTANCE, TransportDeleteIndexAction.class); registerAction(GetIndexAction.INSTANCE, TransportGetIndexAction.class); registerAction(OpenIndexAction.INSTANCE, TransportOpenIndexAction.class); registerAction(CloseIndexAction.INSTANCE, TransportCloseIndexAction.class); registerAction(IndicesExistsAction.INSTANCE, TransportIndicesExistsAction.class); registerAction(TypesExistsAction.INSTANCE, TransportTypesExistsAction.class); registerAction(GetMappingsAction.INSTANCE, TransportGetMappingsAction.class); registerAction(GetFieldMappingsAction.INSTANCE, TransportGetFieldMappingsAction.class, TransportGetFieldMappingsIndexAction.class); registerAction(PutMappingAction.INSTANCE, TransportPutMappingAction.class); registerAction(IndicesAliasesAction.INSTANCE, TransportIndicesAliasesAction.class); registerAction(UpdateSettingsAction.INSTANCE, TransportUpdateSettingsAction.class); registerAction(AnalyzeAction.INSTANCE, TransportAnalyzeAction.class); registerAction(PutIndexTemplateAction.INSTANCE, TransportPutIndexTemplateAction.class); registerAction(GetIndexTemplatesAction.INSTANCE, TransportGetIndexTemplatesAction.class); registerAction(DeleteIndexTemplateAction.INSTANCE, TransportDeleteIndexTemplateAction.class); registerAction(ValidateQueryAction.INSTANCE, TransportValidateQueryAction.class); registerAction(RefreshAction.INSTANCE, TransportRefreshAction.class); registerAction(FlushAction.INSTANCE, TransportFlushAction.class); registerAction(SyncedFlushAction.INSTANCE, TransportSyncedFlushAction.class); registerAction(ForceMergeAction.INSTANCE, TransportForceMergeAction.class); registerAction(UpgradeAction.INSTANCE, TransportUpgradeAction.class); registerAction(UpgradeStatusAction.INSTANCE, TransportUpgradeStatusAction.class); registerAction(UpgradeSettingsAction.INSTANCE, TransportUpgradeSettingsAction.class); registerAction(ClearIndicesCacheAction.INSTANCE, TransportClearIndicesCacheAction.class); registerAction(PutWarmerAction.INSTANCE, TransportPutWarmerAction.class); registerAction(DeleteWarmerAction.INSTANCE, TransportDeleteWarmerAction.class); registerAction(GetWarmersAction.INSTANCE, TransportGetWarmersAction.class); registerAction(GetAliasesAction.INSTANCE, TransportGetAliasesAction.class); registerAction(AliasesExistAction.INSTANCE, TransportAliasesExistAction.class); registerAction(GetSettingsAction.INSTANCE, TransportGetSettingsAction.class); registerAction(IndexAction.INSTANCE, TransportIndexAction.class); registerAction(GetAction.INSTANCE, TransportGetAction.class); registerAction(TermVectorsAction.INSTANCE, TransportTermVectorsAction.class, TransportDfsOnlyAction.class); registerAction(MultiTermVectorsAction.INSTANCE, TransportMultiTermVectorsAction.class, TransportShardMultiTermsVectorAction.class); registerAction(DeleteAction.INSTANCE, TransportDeleteAction.class); registerAction(ExistsAction.INSTANCE, TransportExistsAction.class); registerAction(SuggestAction.INSTANCE, TransportSuggestAction.class); registerAction(UpdateAction.INSTANCE, TransportUpdateAction.class); registerAction(MultiGetAction.INSTANCE, TransportMultiGetAction.class, TransportShardMultiGetAction.class); registerAction(BulkAction.INSTANCE, TransportBulkAction.class, TransportShardBulkAction.class); registerAction(SearchAction.INSTANCE, TransportSearchAction.class); registerAction(SearchScrollAction.INSTANCE, TransportSearchScrollAction.class); registerAction(MultiSearchAction.INSTANCE, TransportMultiSearchAction.class); registerAction(PercolateAction.INSTANCE, TransportPercolateAction.class); registerAction(MultiPercolateAction.INSTANCE, TransportMultiPercolateAction.class, TransportShardMultiPercolateAction.class); registerAction(ExplainAction.INSTANCE, TransportExplainAction.class); registerAction(ClearScrollAction.INSTANCE, TransportClearScrollAction.class); registerAction(RecoveryAction.INSTANCE, TransportRecoveryAction.class); registerAction(RenderSearchTemplateAction.INSTANCE, TransportRenderSearchTemplateAction.class); //Indexed scripts registerAction(PutIndexedScriptAction.INSTANCE, TransportPutIndexedScriptAction.class); registerAction(GetIndexedScriptAction.INSTANCE, TransportGetIndexedScriptAction.class); registerAction(DeleteIndexedScriptAction.INSTANCE, TransportDeleteIndexedScriptAction.class); registerAction(FieldStatsAction.INSTANCE, TransportFieldStatsTransportAction.class);
调用的注册Handler的代码如下:
protected <Request extends TransportRequest> void registerRequestHandler(RequestHandlerRegistry<Request> reg) { synchronized (requestHandlerMutex) {
RequestHandlerRegistry replaced = requestHandlers.get(reg.getAction());
requestHandlers = MapBuilder.newMapBuilder(requestHandlers).put(reg.getAction(), reg).immutableMap(); if (replaced != null) {
logger.warn("registered two transport handlers for action {}, handlers: {}, {}", reg.getAction(), reg, replaced);
}
}
}TransportService里有一个内部类, Adapter:
protected class Adapter implements TransportServiceAdapter

image.png
这个Adapter里有个方法是根据Action获取RequestHandlerRegistry 对象(关键, 后面会用到)
@Override
public RequestHandlerRegistry getRequestHandler(String action) { return requestHandlers.get(action);
}2 以Get来解析
这里以Get操作来解析, 从ActionModule依赖注入到使用Get操作的Handler流程, 中间涉及了Netty的RPC.
这里通过es 的id 来Get读取es的某条记录:
private static void getInfo(Client client) {
GetRequestBuilder getRequestBuilder = client.prepareGet("face_fixedperson", "Fixedperson", "126tc");
GetResponse getFields = getRequestBuilder.execute().actionGet();
String sourceAsString = getFields.getSourceAsString();
System.out.println("-----" + sourceAsString);
}其涉及的流程如下:
1 ActionModule里面:
registerAction(GetAction.INSTANCE, TransportGetAction.class);
----------------------------------------------------------------------------------------@Inject
public TransportGetAction(Settings settings, ClusterService clusterService, TransportService transportService,
IndicesService indicesService, ThreadPool threadPool, ActionFilters actionFilters,
IndexNameExpressionResolver indexNameExpressionResolver) { super(settings, GetAction.NAME, threadPool, clusterService, transportService, actionFilters, indexNameExpressionResolver,
GetRequest.class, ThreadPool.Names.GET); this.indicesService = indicesService; this.realtime = settings.getAsBoolean("action.get.realtime", true);
}
---------------------------------------------------------------------------------------------protected TransportSingleShardAction(Settings settings, String actionName, ThreadPool threadPool, ClusterService clusterService,
TransportService transportService, ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver,
Class<Request> request, String executor) { super(settings, actionName, threadPool, actionFilters, indexNameExpressionResolver, transportService.getTaskManager()); this.clusterService = clusterService; this.transportService = transportService; this.transportShardAction = actionName + "[s]"; this.executor = executor; if (!isSubAction()) {
transportService.registerRequestHandler(actionName, request, ThreadPool.Names.SAME, new TransportHandler());
}
transportService.registerRequestHandler(transportShardAction, request, executor, new ShardTransportHandler());
}2 注册Handler(registerRequestHandler)
public <Request extends TransportRequest> void registerRequestHandler(String action, Class<Request> request, String executor, boolean forceExecution, boolean canTripCircuitBreaker, TransportRequestHandler<Request> handler) {
RequestHandlerRegistry<Request> reg = new RequestHandlerRegistry<>(action, request, taskManager, handler, executor, forceExecution, canTripCircuitBreaker);
registerRequestHandler(reg);
} protected <Request extends TransportRequest> void registerRequestHandler(RequestHandlerRegistry<Request> reg) { synchronized (requestHandlerMutex) {
RequestHandlerRegistry replaced = requestHandlers.get(reg.getAction());
requestHandlers = MapBuilder.newMapBuilder(requestHandlers).put(reg.getAction(), reg).immutableMap(); if (replaced != null) {
logger.warn("registered two transport handlers for action {}, handlers: {}, {}", reg.getAction(), reg, replaced);
}
}
}3 TransportClient端执行prepareGet之后执行execute
根据之前的文章, 我们知道这个请求最终会被代理类真正的调用:
public <Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>> void execute(final Action<Request, Response, RequestBuilder> action, final Request request, ActionListener<Response> listener) { // 比如registerAction(DeleteAction.INSTANCE, TransportDeleteAction.class);即Delete 对应的是 TransportDeleteAction类
final TransportActionNodeProxy<Request, Response> proxy = proxies.get(action);
nodesService.execute(new TransportClientNodesService.NodeListenerCallback<Response>() { @Override
public void doWithNode(DiscoveryNode node, ActionListener<Response> listener) {
proxy.execute(node, request, listener);
}
}, listener);
}
---------------------------------------------------------------------------------------------public void execute(final DiscoveryNode node, final Request request, final ActionListener<Response> listener) {
ActionRequestValidationException validationException = request.validate(); if (validationException != null) {
listener.onFailure(validationException); return;
}
transportService.sendRequest(node, action.name(), request, transportOptions, new ActionListenerResponseHandler<Response>(listener) { @Override
public Response newInstance() { return action.newResponse();
}
});
}上面调用了transportService.sendRequest实际上是RPC,会先判断node是本地节点, 还是远程Server节点, 如果是本地节点则sendLocalRequest, 远程节点则transport.sendRequest(node, requestId, action, request, options);
// 查询的时候先检查目标是否本地nodeif (node.equals(localNode)) {
sendLocalRequest(requestId, action, request);
} else {
transport.sendRequest(node, requestId, action, request, options);
}这里不再说明sendLocalRequest的情况, 这种情况比较简单, 可自行阅读. 这里说明远程Node节点的情况
4 前面文章分析了ES中的NettyTransport的情景(https://www.jianshu.com/p/ad89a0ad0424), 这里就会使用到, 在调用transport.sendRequest之后, Server端Node的Netty就会接受这个请求,Server端的MessageChannelHandler的messageReceived方法就会被触发(因为收到了客户端的数据发送),
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { // .........省略
// 如果是请求, 则处理Request请求, 如果是服务端返回的则走else分支, 执行response的handler
if (TransportStatus.isRequest(status)) { // 是Request请求
handleRequest(ctx.getChannel(), marker, streamIn, requestId, size, version);
} else { // 是Response返回
TransportResponseHandler<?> handler = transportServiceAdapter.onResponseReceived(requestId); // ignore if its null, the adapter logs it
if (handler != null) { if (TransportStatus.isError(status)) {
handlerResponseError(streamIn, handler);
} else {
handleResponse(ctx.getChannel(), streamIn, handler);
}
marker.validateResponse(streamIn, requestId, handler, TransportStatus.isError(status));
}
} // .....省略}因为此处是请求, 所以执行handleRequest方法,
protected String handleRequest(Channel channel, Marker marker, StreamInput buffer, long requestId, int messageLengthBytes,
Version version) throws IOException {
buffer = new NamedWriteableAwareStreamInput(buffer, transport.namedWriteableRegistry); final String action = buffer.readString();
transportServiceAdapter.onRequestReceived(requestId, action);
NettyTransportChannel transportChannel = null; try { final RequestHandlerRegistry reg = transportServiceAdapter.getRequestHandler(action); if (reg == null) { throw new ActionNotFoundTransportException(action);
} if (reg.canTripCircuitBreaker()) {
transport.inFlightRequestsBreaker().addEstimateBytesAndMaybeBreak(messageLengthBytes, "<transport_request>");
} else {
transport.inFlightRequestsBreaker().addWithoutBreaking(messageLengthBytes);
}
transportChannel = new NettyTransportChannel(transport, transportServiceAdapter, action, channel,
requestId, version, profileName, messageLengthBytes); final TransportRequest request = reg.newRequest();
request.remoteAddress(new InetSocketTransportAddress((InetSocketAddress) channel.getRemoteAddress()));
request.readFrom(buffer); // in case we throw an exception, i.e. when the limit is hit, we don't want to verify
validateRequest(marker, buffer, requestId, request, action); if (ThreadPool.Names.SAME.equals(reg.getExecutor())) { //noinspection unchecked
reg.processMessageReceived(request, transportChannel); //具体处理请求. 我们知道请求有多种种类, 不同的Request会使用不同的Handler进行处理
} else {
threadPool.executor(reg.getExecutor()).execute(new RequestHandler(reg, request, transportChannel));
}
} catch (Throwable e) { // the circuit breaker tripped
if (transportChannel == null) {
transportChannel = new NettyTransportChannel(transport, transportServiceAdapter, action, channel,
requestId, version, profileName, 0);
} try {
transportChannel.sendResponse(e);
} catch (IOException e1) {
logger.warn("Failed to send error message back to client for action [" + action + "]", e);
logger.warn("Actual Exception", e1);
}
} return action;
}
---------------------------------------------------------------------------------------------public void processMessageReceived(Request request, TransportChannel channel) throws Exception { final Task task = taskManager.register(channel.getChannelType(), action, request); if (task == null) {
handler.messageReceived(request, channel);
} else { boolean success = false; try {
handler.messageReceived(request, new TransportChannelWrapper(taskManager, task, channel), task);
success = true;
} finally { if (success == false) {
taskManager.unregister(task);
}
}
}
}上面一大串代码, 关键的代码是如下2个:
(1)final RequestHandlerRegistry reg = transportServiceAdapter.getRequestHandler(action);根据Action获取具体的Handler, 还记得2 注册Handler(registerRequestHandler)里面Get操作我们注册的transportService.registerRequestHandler(transportShardAction, request, executor, new ShardTransportHandler());吗? 此处我们的具体Handler就是ShardTransportHandler.
(2)reg.processMessageReceived(request, transportChannel); 就是调用具体的Handler的messageReceived方法.
5 具体Handler处理
第4步分析到实际上执行的就是ShardTransportHandler的messageReceived方法,
// 读取数据组织成 Response, 给客户端 channel 返回。
private class ShardTransportHandler extends TransportRequestHandler<Request> { @Override
public void messageReceived(final Request request, final TransportChannel channel) throws Exception { if (logger.isTraceEnabled()) {
logger.trace("executing [{}] on shard [{}]", request, request.internalShardId);
} // shardOperation主要处理请求中是否有 refresh 选项,然后调用indexShard.getService().get() 读取数据
Response response = shardOperation(request, request.internalShardId);
channel.sendResponse(response);
}
}
---------------------------------------------------------------------------------------------
shardOperation 实际上是TransportGetAction的shardOperation方法.@Override
protected GetResponse shardOperation(GetRequest request, ShardId shardId) {
IndexService indexService = indicesService.indexServiceSafe(shardId.getIndex());
IndexShard indexShard = indexService.shardSafe(shardId.id());// shard 的id 号, 哪个shard
if (request.refresh() && !request.realtime()) {
indexShard.refresh("refresh_flag_get");
}
GetResult result = indexShard.getService().get(request.type(), request.id(), request.fields(),
request.realtime(), request.version(), request.versionType(), request.fetchSourceContext(), request.ignoreErrorsOnGeneratedFields()); return new GetResponse(result);
}6 经过第5步之后, Get请求就会通过操作转向成具体的Lucene的Get操作. 此处细节不在说明.
以上6步就是一个操作的大致流程. 此处只分析了Get操作, 但是ES其他操作的流程和这个流程基本是一样的.
作者:kason_zhang
链接:https://www.jianshu.com/p/0e5e321bd932
随时随地看视频