Es get流程
整体流程协调节点封装请求发送给对应的分片,如果在此分片失败找下一个分片,成功后封装结果返回给客户端
请求入口 RestGetAction @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { final GetRequest getRequest = new GetRequest(request.param("index"), request.param("type"), request.param("id")); getRequest.operationThreaded(true); getRequest.refresh(request.paramAsBoolean("refresh", getRequest.refresh())); getRequest.routing(request.param("routing")); getRequest.parent(request.param("parent")); getRequest.preference(request.param("preference")); getRequest.realtime(request.paramAsBoolean("realtime", getRequest.realtime())); //默认为true 需要刷盘 if (request.param("fields") != null) { throw new IllegalArgumentException("the parameter [fields] is no longer supported, " + "please use [stored_fields] to retrieve stored fields or [_source] to load the field from _source"); } final String fieldsParam = request.param("stored_fields"); if (fieldsParam != null) { final String[] fields = Strings.splitStringByCommaToArray(fieldsParam); if (fields != null) { getRequest.storedFields(fields); } } getRequest.version(RestActions.parseVersion(request)); getRequest.versionType(VersionType.fromString(request.param("version_type"), getRequest.versionType())); getRequest.fetchSourceContext(FetchSourceContext.parseFromRestRequest(request)); return channel -> client.get(getRequest, new RestToXContentListener<GetResponse>(channel) { @Override protected RestStatus getStatus(final GetResponse response) { return response.isExists() ? OK : NOT_FOUND; } }); } 计算往哪个分片上发的算法 private static int calculateScaledShardId(IndexMetaData indexMetaData, String effectiveRouting, int partitionOffset) { final int hash = Murmur3HashFunction.hash(effectiveRouting) + partitionOffset; // we don't use IMD#getNumberOfShards since the index might have been shrunk such that we need to use the size // of original index to hash documents return Math.floorMod(hash, indexMetaData.getRoutingNumShards()) / indexMetaData.getRoutingFactor(); } 主要执行入口 TransportSingleShardAction public void start() { if (shardIt == null) { // just execute it on the local node transportService.sendRequest(clusterService.localNode(), transportShardAction, internalRequest.request(), new TransportResponseHandler<Response>() { @Override public Response newInstance() { return newResponse(); } @Override public String executor() { return ThreadPool.Names.SAME; } @Override public void handleResponse(final Response response) { listener.onResponse(response); } @Override public void handleException(TransportException exp) { listener.onFailure(exp); } }); } else { perform(null); } } private void perform(@Nullable final Exception currentFailure) { Exception lastFailure = this.lastFailure; if (lastFailure == null || TransportActions.isReadOverrideException(currentFailure)) { lastFailure = currentFailure; this.lastFailure = currentFailure; } final ShardRouting shardRouting = shardIt.nextOrNull();//获取下一个副本 if (shardRouting == null) {//如果所有副本都失败 返回失败 Exception failure = lastFailure; if (failure == null || isShardNotAvailableException(failure)) { failure = new NoShardAvailableActionException(null, LoggerMessageFormat.format("No shard available for [{}]", internalRequest.request()), failure); } else { if (logger.isDebugEnabled()) { logger.debug( (org.apache.logging.log4j.util.Supplier<?>) () -> new ParameterizedMessage("{}: failed to execute [{}]", null, internalRequest.request()), failure); } } listener.onFailure(failure); return; } DiscoveryNode node = nodes.get(shardRouting.currentNodeId());//通过路由表找这个node if (node == null) { onFailure(shardRouting, new NoShardAvailableActionException(shardRouting.shardId())); //没有的话 找下一个分片去查 } else { internalRequest.request().internalShardId = shardRouting.shardId(); if (logger.isTraceEnabled()) { logger.trace( "sending request [{}] to shard [{}] on node [{}]", internalRequest.request(), internalRequest.request().internalShardId, node ); } transportService.sendRequestnode(, transportShardAction, internalRequest.request(), new TransportResponseHandler<Response>() { @Override public Response newInstance() { return newResponse(); } @Override public String executor() { return ThreadPool.Names.SAME; } @Override public void handleResponse(final Response response) { listener.onResponse(response); } @Override public void handleException(TransportException exp) { onFailure(shardRouting, exp);//失败的话 找下一个分片继续执行 入口仍然是这个方法只是加了Exception } }); } } } //如果是在本地会发送一个message过去 private void sendLocalRequest(long requestId, final String action, final TransportRequest request, TransportRequestOptions options) { final DirectResponseChannel channel = new DirectResponseChannel(logger, localNode, action, requestId, adapter, threadPool); try { adapter.onRequestSent(localNode, requestId, action, request, options); adapter.onRequestReceived(requestId, action); final RequestHandlerRegistry reg = adapter.getRequestHandler(action); if (reg == null) { throw new ActionNotFoundTransportException("Action [" + action + "] not found"); } final String executor = reg.getExecutor(); if (ThreadPool.Names.SAME.equals(executor)) { //noinspection unchecked reg.processMessageReceived(request, channel); } else { threadPool.executor(executor).execute(new AbstractRunnable() { @Override protected void doRun() throws Exception { //noinspection unchecked reg.processMessageReceived(request, channel); } @Override public boolean isForceExecution() { return reg.isForceExecution(); } @Override public void onFailure(Exception e) { try { channel.sendResponse(e); } catch (Exception inner) { inner.addSuppressed(e); logger.warn( (Supplier<?>) () -> new ParameterizedMessage( "failed to notify channel of error message for action [{}]", action), inner); } } }); } } catch (Exception e) { try { channel.sendResponse(e); } catch (Exception inner) { inner.addSuppressed(e); logger.warn( (Supplier<?>) () -> new ParameterizedMessage( "failed to notify channel of error message for action [{}]", action), inner); } } } 以上为协调节点流程 接收到消息后 private class ShardTransportHandler implements 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); } Response response = shardOperation(request, request.internalShardId); channel.sendResponse(response); } } @Override protected GetResponse shardOperation(GetRequest request, ShardId shardId) { IndexService indexService = indicesService.indexServiceSafe(shardId.getIndex()); IndexShard indexShard = indexService.getShard(shardId.id()); if (request.refresh() && !request.realtime()) {//默认是需要刷盘的。 如果需要刷盘并且非实时的 indexShard.refresh("refresh_flag_get"); } GetResult result = indexShard.getService().get(request.type(), request.id(), request.storedFields(), request.realtime(), request.version(), request.versionType(), request.fetchSourceContext()); return new GetResponse(result); } public GetResult get(String type, String id, String[] gFields, boolean realtime, long version, VersionType versionType, FetchSourceContext fetchSourceContext) { currentMetric.inc(); try { long now = System.nanoTime(); GetResult getResult = innerGet(type, id, gFields, realtime, version, versionType, fetchSourceContext);//根据id查 if (getResult.isExists()) { existsMetric.inc(System.nanoTime() - now); } else { missingMetric.inc(System.nanoTime() - now); } return getResult; } finally { currentMetric.dec(); } } private GetResult innerGet(String type, String id, String[] gFields, boolean realtime, long version, VersionType versionType, FetchSourceContext fetchSourceContext) { fetchSourceContext = normalizeFetchSourceContent(fetchSourceContext, gFields); final Collection<String> types; if (type == null || type.equals("_all")) {//如果没有指定搜索类型 找到这个索引的所有类型 types = mapperService.types(); } else { types = Collections.singleton(type); } Engine.GetResult get = null; for (String typeX : types) { Term uidTerm = mapperService.createUidTerm(typeX, id); if (uidTerm != null) { get = indexShard.get(new Engine.Get(realtime, typeX, id, uidTerm) .version(version).versionType(versionType)); if (get.exists()) { type = typeX; break; } else { get.release(); } } } if (get == null || get.exists() == false) { return new GetResult(shardId.getIndexName(), type, id, -1, false, null, null); } try { // break between having loaded it from translog (so we only have _source), and having a document to load return innerGetLoadFromStoredFields(type, id, gFields, fetchSourceContext, get, mapperService);//从上一步获取到的id lucene的id 然后获取到完整的信息 } finally { get.release(); } } @Override public GetResult get(Get get, Function<String, Searcher> searcherFactory) throws EngineException { assert Objects.equals(get.uid().field(), uidField) : get.uid().field(); try (ReleasableLock ignored = readLock.acquire()) { ensureOpen(); if (get.realtime()) {//如果是实时的 并且版本也正常 刷盘 VersionValue versionValue = versionMap.getUnderLock(get.uid().bytes()); if (versionValue != null) { if (versionValue.isDelete()) { return GetResult.NOT_EXISTS; } if (get.versionType().isVersionConflictForReads(versionValue.version, get.version())) { throw new VersionConflictEngineException(shardId, get.type(), get.id(), get.versionType().explainConflictForReads(versionValue.version, get.version())); } refresh("realtime_get"); } } // no version, get the version from the index, we know that we refresh on flush return getFromSearcher(get, searcherFactory); } } protected final GetResult getFromSearcher(Get get, Function<String, Searcher> searcherFactory) throws EngineException { final Searcher searcher = searcherFactory.apply("get"); final DocIdAndVersion docIdAndVersion; try { docIdAndVersion = VersionsAndSeqNoResolver.loadDocIdAndVersion(searcher.reader(), get.uid()); //调用lucene接口查 } catch (Exception e) { Releasables.closeWhileHandlingException(searcher); //TODO: A better exception goes here throw new EngineException(shardId, "Couldn't resolve version", e); } if (docIdAndVersion != null) { if (get.versionType().isVersionConflictForReads(docIdAndVersion.version, get.version())) { Releasables.close(searcher); throw new VersionConflictEngineException(shardId, get.type(), get.id(), get.versionType().explainConflictForReads(docIdAndVersion.version, get.version())); } } if (docIdAndVersion != null) { // don't release the searcher on this path, it is the // responsibility of the caller to call GetResult.release return new GetResult(searcher, docIdAndVersion);//封装result } else { Releasables.close(searcher); return GetResult.NOT_EXISTS; } }