我尝试在创建Elasticsearch索引后立即执行读操作。以下是重现这种情况的简单代码:
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import static java.net.InetAddress.getLoopbackAddress;
public class ElasticIssue {
static String index = "my_index";
public static void main(String[] args) {
final Client c = getClient();
deleteIndexIfExists(c);
createIndex(c);
//refresh(c);
//flush(c);
//delay();
//indexDoc(c);
getDoc(c);
}
static void getDoc(Client client) {
client.prepareGet(index, "some-type", "1").get();
}
static void indexDoc(Client client) {
client.prepareIndex(index, "another-type", "25").setSource("{}").get();
}
static void createIndex(Client client) {
client.admin().indices().prepareCreate(index).get();
}
static void delay() {
try {Thread.sleep(3000);} catch (InterruptedException e) {}
}
static void flush(Client client) {
client.admin().indices().prepareFlush(index).get();
}
private static void refresh(Client client) {
client.admin().indices().prepareRefresh(index).get();
}
static void deleteIndexIfExists(Client client) {
final IndicesExistsResponse response = client.admin().indices().prepareExists(index).get();
if (response.isExists()) {
deleteIndex(client);
}
}
static void deleteIndex(Client client) {
client.admin().indices().prepareDelete(index).get();
}
static Client getClient() {
final Settings settings = Settings.builder()
.put("cluster.name", "elasticsearch") //default name
.put("node.name", "my-node")
.build();
return TransportClient.builder()
.settings(settings)
.build()
.addTransportAddress(new InetSocketTransportAddress(getLoopbackAddress(), 9300));
}
}
然后我收到以下错误:
Exception in thread "main" NoShardAvailableActionException[No shard available for [get [my_index][some-type][1]: routing [null]]]; nested: RemoteTransportException[[my-node][172.17.0.2:9300][indices:data/read/get[s]]]; nested: IllegalIndexShardStateException[CurrentState[RECOVERING] operations only allowed when shard state is one of [POST_RECOVERY, STARTED, RELOCATED]];
at org.elasticsearch.action.support.single.shard.TransportSingleShardAction$AsyncSingleAction.perform(TransportSingleShardAction.java:199)
at org.elasticsearch.action.support.single.shard.TransportSingleShardAction$AsyncSingleAction.onFailure(TransportSingleShardAction.java:186)
at org.elasticsearch.action.support.single.shard.TransportSingleShardAction$AsyncSingleAction.access$1300(TransportSingleShardAction.java:115)
at org.elasticsearch.action.support.single.shard.TransportSingleShardAction$AsyncSingleAction$2.handleException(TransportSingleShardAction.java:240)
at org.elasticsearch.transport.TransportService$DirectResponseChannel.processException(TransportService.java:855)
at org.elasticsearch.transport.TransportService$DirectResponseChannel.sendResponse(TransportService.java:833)
at org.elasticsearch.transport.TransportService$4.onFailure(TransportService.java:387)
at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:39)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: RemoteTransportException[[my-node][172.17.0.2:9300][indices:data/read/get[s]]]; nested: IllegalIndexShardStateException[CurrentState[RECOVERING] operations only allowed when shard state is one of [POST_RECOVERY, STARTED, RELOCATED]];
Caused by: [my_index][[my_index][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:1035)
at org.elasticsearch.index.shard.IndexShard.get(IndexShard.java:651)
at org.elasticsearch.index.get.ShardGetService.innerGet(ShardGetService.java:173)
at org.elasticsearch.index.get.ShardGetService.get(ShardGetService.java:86)
at org.elasticsearch.action.get.TransportGetAction.shardOperation(TransportGetAction.java:101)
at org.elasticsearch.action.get.TransportGetAction.shardOperation(TransportGetAction.java:44)
at org.elasticsearch.action.support.single.shard.TransportSingleShardAction$ShardTransportHandler.messageReceived(TransportSingleShardAction.java:282)
at org.elasticsearch.action.support.single.shard.TransportSingleShardAction$ShardTransportHandler.messageReceived(TransportSingleShardAction.java:275)
at org.elasticsearch.transport.TransportRequestHandler.messageReceived(TransportRequestHandler.java:33)
at org.elasticsearch.transport.RequestHandlerRegistry.processMessageReceived(RequestHandlerRegistry.java:75)
at org.elasticsearch.transport.TransportService$4.doRun(TransportService.java:376)
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)
at java.lang.Thread.run(Thread.java:745)
尽管已经返回了响应,但Elasticsearch索引创建似乎并不完整。这有点令人沮丧。如果我做任何:延迟,索引任何文档,刷新索引,刷新索引(取消注释任何行);然后读取操作成功执行。
这种行为有什么解释?建议的方法是什么,以确保索引准备好工作?列出的解决方案可以通过实验找到。
我正在使用Elasticsearch 2.3.3和Java 8.所有与Elasticsearch的通信都是使用传输协议(使用Java API)完成的。
为了便于设置,这里有docker命令来获取具有所有必要设置的容器:
docker run -p 9200:9200 -p 9300:9300 elasticsearch:2.3.3 -Des.node.name="my-node"
以下是Elasticsearch Java API的Maven依赖项:
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>2.3.3</version>
</dependency>
答案 0 :(得分:0)
您需要等到创建索引。这是你可以做的,等到索引的健康状态为黄色状态。
索引创建函数后,调用以下函数:
static void indexStatusCheck(Client client) {
ClusterHealthResponse response = client.admin().cluster().prepareHealth().setIndices(index).setWaitForYellowStatus().get();
if (response.getStatus() == ClusterHealthStatus.RED) {
throw Exception("Index not ready");
}
}
然后你可以继续进行getDoc()调用。