ElasticSearch (三)Java集成Elasticsearch RestHighLevelClient

 

1.在spring原有及基礎上新增Maven依賴


        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
            <version>6.3.2</version>
        </dependency>

        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>6.3.2</version>
        </dependency>

2.ES 配置參數

創建 ElasticSearchProperties類
@ConfigurationProperties(prefix = "com.commons.es")
public class ElasticSearchProperties {
    private String host = "localhost";
    private int port = 9200;
    private String schema = "http";
    private int connectTimeOut = 1000;
    private int socketTimeOut = 30000;
    private int connectionRequestTimeOut = 500;
    private int maxConnectNum = 100;
    private int maxConnectPerRoute = 100;
    private boolean uniqueConnectTimeConfig = true;
    private boolean uniqueConnectNumConfig = true;
    private Integer shades = 3;//分片數
    private Integer replicas = 2;//副本數
}

3.ES Java客戶端連接

創建ElasticSearchAutoConfig類
@Configuration
//可根據自己所在的目錄要掃描的參數,如下圖
@ComponentScan(basePackages = "com.manager.commons.es") 
@EnableConfigurationProperties(ElasticSearchProperties.class)
public class ElasticSearchAutoConfig {
    private HttpHost httpHost;
    private RestClientBuilder builder;
    private RestHighLevelClient client;

    @Autowired
    private ElasticSearchProperties elasticSearchProperties;

    @Bean
    public RestHighLevelClient restHighLevelClient() {
        httpHost = new HttpHost(elasticSearchProperties.getHost(), elasticSearchProperties.getPort(), elasticSearchProperties.getSchema());
        builder = RestClient.builder(httpHost);
        if (elasticSearchProperties.isUniqueConnectTimeConfig()) {
            setConnectTimeOutConfig();
        }
        if (elasticSearchProperties.isUniqueConnectNumConfig()) {
            setMutiConnectConfig();
        }
        client = new RestHighLevelClient(builder);
        return client;
    }

    /**
     * 異步httpclient的連接延時配置
     */
    public void setConnectTimeOutConfig() {
        builder.setRequestConfigCallback(requestConfigBuilder -> {
            requestConfigBuilder.setConnectTimeout(elasticSearchProperties.getConnectTimeOut());
            requestConfigBuilder.setSocketTimeout(elasticSearchProperties.getSocketTimeOut());
            requestConfigBuilder.setConnectionRequestTimeout(elasticSearchProperties.getConnectionRequestTimeOut());
            return requestConfigBuilder;
        });
    }


    /**
     * 異步httpclient的連接數配置
     */
    public void setMutiConnectConfig() {
        builder.setHttpClientConfigCallback(httpClientBuilder -> {
            httpClientBuilder.setMaxConnTotal(elasticSearchProperties.getMaxConnectNum());
            httpClientBuilder.setMaxConnPerRoute(elasticSearchProperties.getMaxConnectPerRoute());
            return httpClientBuilder;
        });
    }

    /**
     * 關閉連接
     */
    public void close() {
        if (client != null) {
            try {
                client.close();
            } catch (IOException e) {
                log.error("es close error", e);
            }
        }
    }
}

4.創建索引並驗證結果


/**
 * 數據類型
 *
 * @author CHANG
 * @date 2019/7/21 14:43
 */
public interface DailyEsEntity {

    Map<String, Object> genInitMap();

    Map<String, String> DATE_MAP = Collections.unmodifiableMap(new HashMap() {
        {
            put("type", "date");
        }
    });
    Map<String, String> LONG_MAP = Collections.unmodifiableMap(new HashMap() {
        {
            put("type", "long");
        }
    });
    Map<String, String> KEYWORD_MAP = Collections.unmodifiableMap(new HashMap() {
        {
            put("type", "keyword");
        }
    });
    Map<String, String> INTEGER_MAP = Collections.unmodifiableMap(new HashMap() {
        {
            put("type", "integer");
        }
    });
    Map<String, String> BOOLEAN_MAP = Collections.unmodifiableMap(new HashMap() {
        {
            put("type", "boolean");
        }
    });
    Map<String, String> TEXT_MAP = Collections.unmodifiableMap(new HashMap() {
        {
            put("type", "text");
        }
    });

}
/**
 *自定義註解標識文檔
 * @author Chang
 * @date 2019/3/27 14:09
 */
@Qualifier
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface ESDocument {
    /**
     * 標識文檔
     * @return indexName
     */
    String indexName();

    /**
     *是否是文檔
     * @return  boolean
     */
    boolean dailyIndex() default false;
}
/**
 *es文檔mapping及類型
 * @author CHANG
 * @date 2019/7/21 14:34
 */
@Data
@ESDocument(indexName = "user_result", dailyIndex = true)
public class User implements DailyEsEntity {
    public static final String USER_INDEX = "user_result";

    private Long id;
    private String name;
    private Integer age;
    private Boolean isDelete;
    private Data createTime;

    @Override
    public Map<String, Object> genInitMap() {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("id", LONG_MAP);
        map.put("name", KEYWORD_MAP);
        map.put("age", INTEGER_MAP);
        map.put("isDelete", BOOLEAN_MAP);
        map.put("createTime", DATE_MAP);
        return map;
    }
}

/**
 * es索引創建
 * @author CHANG
 * @date 2019/7/21 15:01
 */
@Slf4j
public class ESInitManager {
    @Autowired
    private RestHighLevelClient restHighLevelClient;
    @Autowired
    private ElasticSearchProperties elasticSearchProperties;

    /**
     * 判斷index是否存在
     *
     * @param index index
     * @return indexExists 判斷索引是否存在
     * @throws Exception ex
     */
    boolean indexExists(String index) throws Exception {
        GetIndexRequest request = new GetIndexRequest();
        request.indices(index);
        request.local(false);
        request.humanReadable(true);
        boolean exists = restHighLevelClient.indices().exists(request);
        return exists;
    }

    /**
     * 創建索引
     *
     * @param index      索引
     * @param indexType  類型
     * @param properties indexType 數據類型
     * @return boolean
     */
    public boolean init(String index, String indexType, Map<String, Object> properties) {
        try {
            log.info("init {}", index);
            if (indexExists(index)) {
                return true;
            }
            CreateIndexRequest request = new CreateIndexRequest(index);
            request.settings(Settings.builder()
                    .put("index.number_of_shards", elasticSearchProperties.getShades())
                    .put("index.number_of_replicas", elasticSearchProperties.getReplicas())); //副本數
            Map<String, Object> jsonMap = new HashMap<>();
            Map<String, Object> mapping = new HashMap<>();
            mapping.put("properties", properties);
            jsonMap.put(indexType, mapping);
            request.mapping(indexType, jsonMap);
            CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(request);
            boolean acknowledged = createIndexResponse.isAcknowledged();
            log.info("CreateIndexResponse " + acknowledged);
            return acknowledged;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

}

/**
 * @author CHANG
 * @date 2019/7/21 15:14
 */
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
@Slf4j
public class ESInitManagerTest {

    @Autowired
    private ESInitManager esInitManager;


    /**
     * 這裏我採用索引與類型的名字一樣可根據自己的需求改變名稱
     */
    @Test
    public void init() {
        User user = new User();
        boolean init = esInitManager.init(user.USER_INDEX, user.USER_INDEX, user.genInitMap());
        log.info("init {}", init);
    }
}

5.es單節點創建索引副本爲分配的問題

上面截圖可以看出存在3個unassigned的分片,新建索引user_result的時候,分片數爲3,副本數爲2,新建之後集羣狀態成爲yellow,其根本原因是因爲集羣存在沒有啓用的副本分片。


副本分片的主要目的就是爲了故障轉移,如果持有主分片的節點掛掉了,一個副本分片就會晉升爲主分片的角色。
那麼可以看出來副本分片和主分片是不能放到一個節點上面的,可是在只有一個節點的集羣裏,副本分片沒有辦法分配到其他的節點上,所以出現所有副本分片都unassigned得情況。

因爲只有一個節點,如果存在主分片節點掛掉了,那麼整個集羣理應就掛掉了,不存在副本分片升爲主分片的情況。
解決辦法就是,在單節點的elasticsearch集羣,刪除存在副本分片的索引,新建索引的副本都設爲0。然後再查看集羣狀態

//修改副本數
@ConfigurationProperties(prefix = "com.commons.es")
public class ElasticSearchProperties {
    private String host = "localhost";
    private int port = 9200;
    private String schema = "http";
    private int connectTimeOut = 1000;
    private int socketTimeOut = 30000;
    private int connectionRequestTimeOut = 500;
    private int maxConnectNum = 100;
    private int maxConnectPerRoute = 100;
    private boolean uniqueConnectTimeConfig = true;
    private boolean uniqueConnectNumConfig = true;
    private Integer shades = 3;//分片數
    private Integer replicas = 0;//副本數
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章