运行测试时,ElasticSearch会随机失败

时间:2017-05-04 04:29:35

标签: elasticsearch

我有一个测试ElasticSearch框(2.3.0),我使用ES的测试以随机顺序失败,这实在令人沮丧(失败,所有分片失败异常)。

查看elastic_search.log文件,它只显示了我

[2017-05-04 04:19:15,990][DEBUG][action.search.type       ] [es-testing-1] All shards failed for phase: [query]
RemoteTransportException[[es-testing-1][127.0.0.1:9300][indices:data/read/search[phase/query]]]; nested: IllegalIndexShardStateException[CurrentState[RECOVERING] operations only allowed when shard state is one of [POST_RECOVERY, STARTED, RELOCATED]];
Caused by: [derp_test][[derp_test][3]] IllegalIndexShardStateException[CurrentState[RECOVERING] operations only allowed when shard state is one of [POST_RECOVERY, STARTED, RELOCATED]]
    at org.elasticsearch.index.shard.IndexShard.readAllowed(IndexShard.java:993)
    at org.elasticsearch.index.shard.IndexShard.acquireSearcher(IndexShard.java:814)
    at org.elasticsearch.search.SearchService.createContext(SearchService.java:641)
    at org.elasticsearch.search.SearchService.createAndPutContext(SearchService.java:618)
    at org.elasticsearch.search.SearchService.executeQueryPhase(SearchService.java:369)
    at org.elasticsearch.search.action.SearchServiceTransportAction$SearchQueryTransportHandler.messageReceived(SearchServiceTransportAction.java:368)
    at org.elasticsearch.search.action.SearchServiceTransportAction$SearchQueryTransportHandler.messageReceived(SearchServiceTransportAction.java:365)
    at org.elasticsearch.transport.TransportService$4.doRun(TransportService.java:350)
    at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

知道发生了什么事吗?到目前为止,我的研究只告诉我这很可能是由于腐败的translog - 但我不认为删除translog会有所帮助,因为测试会删除每个命名空间的测试索引

ES测试盒有3.5GB RAM,使用2.5GB堆大小,测试期间CPU使用率非常正常(达到峰值15%)

澄清一下:当我说测试失败时,我的意思是上面提到的奇怪异常的错误(由于不正确的值而没有失败测试)。我在每次插入/更新操作后都进行了手动刷新,因此值是正确的。

4 个答案:

答案 0 :(得分:1)

在调查ElasticSearch日志文件(在DEBUG级别)和源代码之后,结果发现实际发生的是在创建索引之后,分片正在进入RECOVERING状态,有时我的测试尝试执行查询当分片尚未激活时ElasticSearch - 因此异常。

修复很简单 - 在创建索引之后,只需等待使用setWaitForActiveShards函数激活分片并更加偏执,我还添加了setWaitForYellowStatus

答案 1 :(得分:0)

建议使用ESIntegTestCase进行集成测试。

ESIntegTestCase有一些辅助方法,例如:ensureGreenrefresh ...以确保 Elasticsearch 已准备好继续测试。并且您可以配置node settings进行测试。

如果直接使用Elasticsearch作为测试框,可能会导致各种问题:

  1. 就像你的Exception一样,这似乎正在恢复索引的分片 derp_test
  2. 即使您已将数据编入索引,但当您立即搜索失败时,由于群集需要刷新刷新 ...
  3. 那些大多数问题都可以使用Thread.sleep等待一段时间来修复:),但这是一个糟糕的方法。

答案 2 :(得分:0)

尝试在插入数据后和执行查询之前手动刷新索引,以确保数据可搜索。

或者:

答案 3 :(得分:0)

可能还有另一个原因。我的Elasticsearch单元测试存在相同的问题,起初我认为问题的根本原因是.Net Core或Nest或代码之外的其他地方,因为该测试将成功运行 调试模式(在调试测试时),但是在发布模式下随机失败(运行测试时)

经过大量调查和尝试和错误,我发现问题的根本原因(在我的情况下)是并发!! 或另一方面 >种族条件曾经发生

由于测试是同时运行的,所以我通常在测试类构造函数上重新创建索引(初始化和准备)并将其种子化(这意味着在每个测试的开始时执行),并且由于测试将同时运行,因此竞争条件很可能会发生,并且让我的测试失败

这是我的初始化代码,导致运行测试时(在发布模式下)测试随机失败

 public BaseElasticDataTest(RootFixture fixture)
        : base(fixture)
    {
        ElasticHelper = fixture.Builder.Build<ElasticDataProvider<FakePersonIndex>();
        deleteFakeIndex();
        createFakeIndex();
        fillFakeIndexData();
    }

上面的代码用于同时在每个测试上运行。我通过在每个测试类中仅执行一次初始化代码(一次用于该测试类中的所有测试用例)来解决问题,问题就消失了。

这是我的固定测试类构造函数代码:

 static bool initialized = false;
 public BaseElasticDataTest(RootFixture fixture)
        : base(fixture)
    {
        ElasticHelper = fixture.Builder.Build<ElasticDataProvider<FakePersonIndex>>();
        if (!initialized)
        {
            deleteFakeIndex();
            createFakeIndex();
            fillFakeIndexData();
            //for concurrency
            System.Threading.Thread.Sleep(100);
            initialized = true;
        }

    }

希望有帮助