我有一个测试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%)
澄清一下:当我说测试失败时,我的意思是上面提到的奇怪异常的错误(由于不正确的值而没有失败测试)。我在每次插入/更新操作后都进行了手动刷新,因此值是正确的。
答案 0 :(得分:1)
在调查ElasticSearch日志文件(在DEBUG级别)和源代码之后,结果发现实际发生的是在创建索引之后,分片正在进入RECOVERING
状态,有时我的测试尝试执行查询当分片尚未激活时ElasticSearch - 因此异常。
修复很简单 - 在创建索引之后,只需等待使用setWaitForActiveShards
函数激活分片并更加偏执,我还添加了setWaitForYellowStatus
答案 1 :(得分:0)
建议使用ESIntegTestCase进行集成测试。
ESIntegTestCase
有一些辅助方法,例如:ensureGreen
和refresh
...以确保 Elasticsearch 已准备好继续测试。并且您可以配置node settings
进行测试。
如果直接使用Elasticsearch
作为测试框,可能会导致各种问题:
Exception
一样,这似乎正在恢复索引的分片
derp_test
。那些大多数问题都可以使用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;
}
}
希望有帮助