有什么方法可以保证删除ElasticSearch索引

时间:2019-06-13 12:01:58

标签: java elasticsearch automated-tests race-condition

在某些自动化测试中,我尝试使用ElasticSearch的高级rest客户端(版本6.4)在每次测试开始时删除并立即重新创建索引,如下所示:

DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(indexName);
deleteIndexRequest.indicesOptions(IndicesOptions.lenientExpandOpen());
client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);

CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName);
request.mapping("_doc", "{...}", XContentType.JSON);
client.indices().create(request, RequestOptions.DEFAULT);

我的问题是,我的测试在创建索引时断断续续地失败,并出现错误:

{"error": {"root_cause":[{"type":"resource_already_exists_exception","reason":"index [(index-name)/(UUID)] already exists, ...,}] "status":400}

我运行的测试越多,我越有可能看到该错误,这似乎是一个竞争条件的有力指示-大概是在我尝试重新创建索引时,以前的删除操作并不总是完成的

这是以下事实的备份:如果我在删除操作之后立即放置一个断点,并手动运行一个curl请求以查看我尝试删除的索引,我发现它仍然存在一些时间;在这些情况下,如果我继续测试,就会出现上述错误。

我尝试声明对删除操作的响应的isAcknowledged()方法,但是即使在发生错误的情况下,它总是返回true

我还尝试过在创建操作之前进行exists()检查。有趣的是,如果我在没有断点的情况下运行测试,即使发生错误,exists()检查也会始终返回false(即索引不存在),但是如果在创建操作之前放置了一个断点,那么在发生错误的情况下,exists()检查将返回true

我有点茫然。据我了解,我的请求应该是同步的,并且从对this question的评论中可以看出,delete()操作仅在绝对删除索引后才返回。

我怀疑问题的关键在于这些测试正在3个节点的群集上运行。在设置客户端时,我只针对以下节点之一:

client = new RestHighLevelClient(RestClient.builder(new HttpHost("example.com", 9200, "https")));

但是我可以看到每个操作都被复制到其他两个节点上。

当我在创建操作之前停止断点时,如果没有删除索引,则可以看到它在任何节点上都没有删除,而且等待多长时间似乎也没关系,它永远不会得到删除。

在创建索引之前,是否可以通过某些方法可靠地确定索引是否已删除?还是我需要在之前做一些尝试,以确保删除操作成功?

1 个答案:

答案 0 :(得分:1)

嘿,我认为有很多事情要考虑。对于其中一个,我将使用curl或某种形式的rest client测试所有内容,直到我开始执行任何代码为止。可能只是从概念上帮助您,但这只是我的意见。

这是您应该考虑的一件事: “如果使用了外部版本控制变体,则删除操作会自动创建一个索引(如果之前未创建过的话)(请查看用于手动创建索引的创建索引API)。” https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-delete.html 哪种方法可以解释为什么exist()将返回false。因此,如果使用外部版本控制版本,则delete选项实际上会在删除索引之前创建具有相同名称的索引。

您提到了您正在使用三节点群集的事实。您可以尝试的方法是: “发出删除请求时,可以将wait_for_active_shards参数设置为要求最小数量的分片副本处于活动状态,然后再开始处理删除请求。”这里是一个非常详细的解释,值得一读:https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html#index-wait-for-active-shards

我建议您尝试:

curl -X DELETE 127.0.0.1:9200/fooindex?wait_for_active_shards=3

您说您的集群中有3个节点,所以这意味着:“ ...索引操作在继续操作之前将需要3个活动的分片副本,这是可以满足的,因为集群中有3个活动的节点,每个节点一个拿着碎片的副本。” 根据此处的文档,此检查可能不是100%防水的:https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html#index-wait-for-active-shards “重要的是要注意,此设置大大降低了写操作未写入所需数量的分片副本的机会,但并不能完全消除这种可能性,因为此检查是在写操作开始之前进行的。目前,在任何数量的分片副本上复制仍然有可能失败,但在主副本上仍然可以成功。写入操作响应的_shards部分显示了复制成功/失败的分片副本的数量。”因此也许使用此参数,但是让您的代码检查响应以查看是否有任何操作失败。

您还可以尝试以下操作: (我似乎找不到很好的文档来备份此信息) 这样应该可以告诉您群集是否还不准备接受删除。

curl -X DELETE 127.0.0.1:9200/index?wait_for_completion=true