公司ES升級帶來的坑怎麼填?

猿天地發表於2018-11-26

前言

公司的ES最近需要全部進行升級,目的是方便維護和統一管理。以前的版本不統一,這次準備統一升級到一個固定的版本。

同時還會給ES加上許可權控制,雖然都是部署在內網,為了防止誤操作,加上許可權還是有必要的。

帶來的問題就是我這邊的程式得改了,目前用的是Spring Data Elasticsearch來操作ES。

問題

首先版本從5.x升級到6.4.0,我這邊用的Spring Boot是2.0.1版本,這塊是相容的,沒有影響。唯一導致我這邊要改動的就是許可權這塊。

在Spring Boot的文件中,提供了三種操作ES的框架,有兩種是走Http協議的,也就是操作9200埠,是可以直接支援使用者名稱和密碼配置的。

elasticsearch-rest-client

spring.elasticsearch.rest.uris=http://search.example.com:9200
spring.elasticsearch.rest.username=user
spring.elasticsearch.rest.password=secret

JestClient:

spring.elasticsearch.jest.uris=http://search.example.com:9200
spring.elasticsearch.jest.read-timeout=10000
spring.elasticsearch.jest.username=user
spring.elasticsearch.jest.password=secret

偏偏我用的是第三種Spring Data Elasticsearch,沒有認證資訊的配置,但是有一個擴充套件屬性properties

@ConfigurationProperties(prefix = "spring.data.elasticsearch")
public class ElasticsearchProperties {

    /**
     * Elasticsearch cluster name.
     */

    private String clusterName = "elasticsearch";

    /**
     * Comma-separated list of cluster node addresses.
     */

    private String clusterNodes;

    /**
     * Additional properties used to configure the client.
     */

    private Map<StringString> properties = new HashMap<>();
}

在TransportClientFactoryBean中初始化Settings的時候,會取properties中值

private Settings settings({
    if (properties != null) {
            Settings.Builder builder = Settings.builder();

            properties.forEach((key, value) -> {
                builder.put(key.toString(), value.toString());
            });

            return builder.build();
    }
    return Settings.builder()
            .put("cluster.name", clusterName)
            .put("client.transport.sniff", clientTransportSniff)
            .put("client.transport.ignore_cluster_name", clientIgnoreClusterName)
            .put("client.transport.ping_timeout", clientPingTimeout)
            .put("client.transport.nodes_sampler_interval", clientNodesSamplerInterval)
            .build();
}

於是我在properties 中加上認證資訊的配置發現還是不行,因為這個全新認證是擴充套件的,需要增加x-pack-transport才行。

<!-- add the x-pack jar as a dependency -->
<dependency>
      <groupId>org.elasticsearch.client</groupId>
      <artifactId>x-pack-transport</artifactId>
      <version>6.4.2</version>
</dependency>

噁心的是中央倉庫沒有,還得指定倉庫:

<repositories>
      <!-- add the elasticsearch repo -->
      <repository>
         <id>elasticsearch-releases</id>
         <url></url>
         <releases>
            <enabled>true</enabled>
         </releases>
         <snapshots>
            <enabled>false</enabled>
         </snapshots>
      </repository>
</repositories>

當你加入這些依賴之後你會發現,還是不能採用spring.data.elasticsearch.xxx這種方式直接配置認證資訊,因為底層不是用的xpack擴充套件的client構造的, 用的是PreBuiltTransportClient,看下程式碼:

protected void buildClient() throws Exception {

    client = new PreBuiltTransportClient(settings());

    clusterNodes.stream() //
            .peek(it -> logger.info("Adding transport node : " + it.toString())) //
            .forEach(client::addTransportAddress);

    client.connectedNodes();
}

最終還是放棄了自動配置的方式,自己手動配置定義Client來支援許可權認證。

@Bean
public Client client() {
    try {
        Settings.Builder builder = Settings.builder()
                .put("client.transport.ping_timeout", pingTimeout)
                .put("cluster.name", clusterName)
                .put("xpack.security.user", username + ":" + password)
                .put("xpack.security.transport.ssl.enabled""true")
                .put("xpack.security.transport.ssl.truststore.path", keystorePath)
                .put("xpack.security.transport.ssl.keystore.path", keystorePath)
                .put("xpack.security.transport.ssl.verification_mode""certificate");
        Settings settings = builder.build();
        String[] nodes = clusterNodes.split(",");
        TransportAddress[] addressArray = new TransportAddress[nodes.length];
        for (int i = 0; i < nodes.length; i++) {
            String[] nodeArray = nodes[i].split(":");
            addressArray[i] = new TransportAddress(InetAddress.getByName(nodeArray[0]), Integer.parseInt(nodeArray[1]));
        }
        return new PreBuiltXPackTransportClient(settings).addTransportAddresses(addressArray);
    } catch (Exception e) {
        logger.error("初始化ESClient異常", e);
    }
    return null;
}
  • username:使用者名稱

  • password:密碼

  • keystorePath:證照地址,會有一個.p12的證照

不知大家發現沒有,看上去我們自定義的程式碼也沒什麼特別,關鍵點在於PreBuiltXPackTransportClient,框架中用的是PreBuiltTransportClient,所以我們才需要自定義。

配置完了你會發現還是不行,各種jar衝突,Spring Boot的版本還需要升級,於是只能升到目前最新的2.1.0版本。升級完之後又有坑了。

升級之前Data中的註解,要指定型別,keyword變成了Keyword

@Field(type=FieldType.Keyword)

ES的這個Field註解沒有別名對映的屬性,就是我es中存的u_name, 實體類中寫的是username,這個確實不太方便,像data mongodb中都有這樣的功能,有知道怎麼解決的要給我留言哈,學習下。

然後就是security的一個坑了,升級之後security版本也升級了,下載下來的jar包用不了,錯誤如下:

公司ES升級帶來的坑怎麼填?

一開始以為是網路原因,沒下載完,然後重新刪了再下,試了5次還是不行,最後沒辦法,我手動下載了spring-security-config這個包,替換了本地倉庫的jar。

下載地址:https://mvnrepository.com/artifact/org.springframework.security/spring-security-config/5.1.1.RELEASE

以上就是這次升級過程中踩過的坑,分享給大家。這次只是客戶端這塊的改變,至於ES是怎麼開啟許可權認證的我這邊就不做講解了,因為這塊不是我弄的,所以我也不熟悉,等後面有機會我也去研究研究可以給大家分享,反正是基於xpack搞的。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31561268/viewspace-2221582/,如需轉載,請註明出處,否則將追究法律責任。

相關文章