調用es接口等待時間過長
查詢es集羣狀態:curl -XGET http://192.168.0.12:9200/_cluster/health?pretty
發現集羣狀態爲red "status" : "red"
查看每個索引的狀態:curl -XGET http://192.168.0.12:9200/_cat/indices?v
發現有許多之前安裝X-Pack時候自帶的無用索引(X-Pack是kibana開啓系統監控必須集成的組件,用了一段時間後面過期了需要證書,就把X-Pack給下了)
刪除無用索引(帶通配符):curl -XDELETE "http://192.168.0.12:9200/.monitoring-*"
查看所以索引分配方式:curl -s "http://192.168.0.12:9200/_cat/shards"
過濾查看所有未分配索引的方式:curl -s "http://192.168.0.12:9200/_cat/shards" | grep UNASSIGNED
發現有3個索引的狀態是UNASSIGNED(每個索引原先4個primary,但是集羣僅有3個節點,有一個主分片沒有被分配)
自動分配分片(沒試成功):curl -XPOST http://192.168.0.12:9200/_cluster/reroute?retry_failed
手動移動分片(沒試成功):
curl -XPOST 'http://192.168.0.12:9200/_cluster/reroute?pretty' -d '
{
"commands" : [ {
"allocate_stale_primary" : {
"index" : "imei",
"shard" :0,
"node" : "hadoop2",
"accept_data_loss" : true
}
}]
}'
想嘗試動態修改分片數量(癡心妄想,只能動態修改副本數):curl -XPUT 'http://192.168.0.12:9200/users/_settings' -d '{"number_of_shards": 3}'
沒法之後嘗試重建索引,將分片數量設爲3,感覺用命令太麻煩了,直接上java方法比較方便:
/*索引重建遷移大法*/
private static void indexMigration() throws UnknownHostException {
String node = "192.168.0.12";
int port = 9300;
String cn = "my-application";
Settings settings = Settings.builder()
.put("cluster.name", cn)//設置ES實例的名稱
.put("client.transport.sniff", true)// 自動嗅探發現集羣節點
.build();
TransportClient client = new PreBuiltTransportClient(settings);
client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(node), port));
log.info("初始化客戶端成功");
List<Map<String, Object>> addList = new ArrayList<>();
//指定一個index和type
SearchRequestBuilder search = client.prepareSearch("users2").setTypes("type");
//使用原生排序優化性能
//search.addSort("_doc", SortOrder.ASC);
search.addSort("_doc", SortOrder.ASC);
//設置每批讀取的數據量
search.setSize(100);
//默認是查詢所有
search.setQuery(QueryBuilders.queryStringQuery("*:*"));
//設置 search context 維護1分鐘的有效期
search.setScroll(TimeValue.timeValueMinutes(1));
//獲得首次的查詢結果
SearchResponse scrollResp = search.get();
//打印命中數量、
log.info("命中總數量:" + scrollResp.getHits().getTotalHits());
int count = 1;
do {
log.info("第" + count + "次打印數據:");
for (SearchHit hit : scrollResp.getHits().getHits()) {
addList.add(hit.getSource());
}
count++;
//將scorllId循環傳遞
scrollResp = client.prepareSearchScroll(scrollResp.getScrollId()).setScroll(TimeValue.timeValueMinutes(1)).execute().actionGet();
} while (scrollResp.getHits().
getHits().length != 0);
//當searchHits的數組爲空的時候結束循環,至此數據全部讀取完畢
BulkRequestBuilder bulkRequest = client.prepareBulk();
for (
int i = 0; i < addList.size(); i++)
{
bulkRequest.add(client.prepareIndex("users", "type").setSource(addList.get(i)));
// 每1000條提交一次
if (i % 1000 == 0) {
bulkRequest.execute().actionGet();
bulkRequest = client.prepareBulk();
}
}
bulkRequest.execute().
actionGet();
}
public static void main(String[] args) throws UnknownHostException {
indexMigration();
}
最後通過新建合適的索引,把原先的數據遷移過來,再重構舊索引,將數據導入回去後,集羣狀態恢復正常。
測試api的時候發現這樣做的話貌似_id被系統設爲自動生成(起初將某些字段同樣給_id賦值,本來是想省一個字段,但是留個心眼在結構裏都把字段寫上了),不過還好當時所有有需要的字段都預留下來了,修改一下方法裏查詢的字段名即可。
重新測試調用api,穩妥的一匹
挺好的shard問題解決方案: