1.概述
转载并且补充:es 写入流程
读取这篇文章的时候先看看
【Elasticsearch】了解Elasticsearch写入磁盘的数据
然后再看看
写索引后端变化太大,等以后熟悉了再补充
Es写索引包括协调节点流程和节点写索引的流程
-
协调节点主要做索引的预处理、检查、分发任务
-
节点执行完后发发送给主分片所在节点,该节点把response发送给协调节点,协调节点发送给用户
2.源码分析
Elasticsearch构建请求有两种方式:
Restful API
Java Cliet API (或其他语言)
下面是两种请方式的实例(效果一样):
Restful API
POST /blog/blog/1
{
"title":"我是一篇博客",
"content":"十九大终于闭幕了"
}
该restful 请求最终会被RestIndexAction处理,源码如下:
public class RestIndexAction extends BaseRestHandler {
private static final DeprecationLogger deprecationLogger = new DeprecationLogger(
LogManager.getLogger(RestDeleteAction.class));
public static final String TYPES_DEPRECATION_MESSAGE = "[types removal] Specifying types in document " +
"index requests is deprecated, use the typeless endpoints instead (/{index}/_doc/{id}, /{index}/_doc, " +
"or /{index}/_create/{id}).";
@Override
public List<Route> routes() {
return unmodifiableList(asList(
new Route(POST, "/{index}/_doc/{id}"),
new Route(PUT, "/{index}/_doc/{id}"),
new Route(POST, "/{index}/{type}/{id}"),
new Route(PUT, "/{index}/{type}/{id}")));
}
@Override
public String getName() {
return "document_index_action";
}
public static final class CreateHandler extends RestIndexAction {
@Override
public String getName() {
return "document_create_action";
}
@Override
public List<Route> routes() {
return unmodifiableList(asList(
new Route(POST, "/{index}/_create/{id}"),
new Route(PUT, "/{index}/_create/{id}"),
new Route(POST, "/{index}/{type}/{id}/_create"),
new Route(PUT, "/{index}/{type}/{id}/_create")));
}
@Override
public RestChannelConsumer prepareRequest(RestRequest request, final NodeClient client) throws IOException {
validateOpType(request.params().get("op_type"));
request.params().put("op_type", "create");
return super.prepareRequest(request, client);
}
void validateOpType(String opType) {
if (null != opType && false == "create".equals(opType.toLowerCase(Locale.ROOT))) {
throw new IllegalArgumentException("opType must be 'create', found: [" + opType + "]");
}
}
}
public static final class AutoIdHandler extends RestIndexAction {
private final Supplier<DiscoveryNodes> nodesInCluster;
public AutoIdHandler(Supplier<DiscoveryNodes> nodesInCluster) {
this.nodesInCluster = nodesInCluster;
}
@Override
public String getName() {
return "document_create_action_auto_id";
}
@Override
public List<Route> routes() {
return unmodifiableList(asList(
new Route(POST, "/{index}/_doc"),
new Route(POST, "/{index}/{type}")));
}
@Override
public RestChannelConsumer prepareRequest(RestRequest request, final NodeClient client) throws IOException {
assert request.params().get("id") == null : "non-null id: " + request.params().get("id");
if (request.params().get("op_type") == null && nodesInCluster.get().getMinNodeVersion().onOrAfter(Version.V_7_5_0)) {
// default to op_type create
request.params().put("op_type", "create");
}
return super.prepareRequest(request, client);
}
}
@Override
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
IndexRequest indexRequest;
// 获取请求中的的index,type,id,并构建一个IndexRequest,用于创建索引的请求
final String type = request.param("type");
if (type != null && type.equals(MapperService.SINGLE_MAPPING_NAME) == false) {
deprecationLogger.deprecatedAndMaybeLog("index_with_types", TYPES_DEPRECATION_MESSAGE);
indexRequest = new IndexRequest(request.param("index"), type, request.param("id"));
} else {
indexRequest = new IndexRequest(request.param("index"));
indexRequest.id(request.param("id"));
}
// 获取请求中的routing参数
indexRequest.routing(request.param("routing"));
indexRequest.setPipeline(request.param("pipeline"));
indexRequest.source(request.requiredContent(), request.getXContentType());
indexRequest.timeout(request.paramAsTime("timeout", IndexRequest.DEFAULT_TIMEOUT));
indexRequest.setRefreshPolicy(request.param("refresh"));
indexRequest.version(RestActions.parseVersion(request));
indexRequest.versionType(VersionType.fromString(request.param("version_type"), indexRequest.versionType()));
indexRequest.setIfSeqNo(request.paramAsLong("if_seq_no", indexRequest.ifSeqNo()));
indexRequest.setIfPrimaryTerm(request.paramAsLong("if_primary_term", indexRequest.ifPrimaryTerm()));
String sOpType = request.param("op_type");
String waitForActiveShards = request.param("wait_for_active_shards");
if (waitForActiveShards != null) {
indexRequest.waitForActiveShards(ActiveShardCount.parseString(waitForActiveShards));
}
if (sOpType != null) {
indexRequest.opType(sOpType);
}
return channel ->
client.index(indexRequest, new RestStatusToXContentListener<>(channel, r -> r.getLocation(indexRequest.routing())));
}
}
然后主要看代码
channel ->client.index(
这里会调用到
org.elasticsearch.client.support.AbstractClient#index(org.elasticsearch.action.index.IndexRequest, org.elasticsearch.action.ActionListener<org.elasticsearch.action.index.IndexResponse>)
@Override
public void index(final IndexRequest request, final ActionListener<IndexResponse> listener) {
execute(IndexAction.INSTANCE, request, listener);
}
@Override
public final <Request extends ActionRequest, Response extends ActionResponse> void execute(
ActionType<Response> action, Request request, ActionListener<Response> listener) {
listener = threadedWrapper.wrap(listener);
doExecute(action, request, listener);
}