更新时间:2024-09-14 GMT+08:00

通过Spring Boot接入Elasticsearch集群

本文介绍通过Spring Boot访问CSS集群的配置说明。Spring Boot接入集群有3种方式:

Spring Boot的具体使用方式请参见官方文档:https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/

注意事项

  • 建议Elasticsearch Rest High Level Client的版本和Elasticsearch的版本保持一致,例如需要访问的Elasticsearch集群版本是7.10.2,则使用的Elasticsearch Rest High Level Client客户端版本建议也是7.10.2。
  • 本章节以2.5.5版本Spring Boot为例介绍Spring Boot接入集群的方式,对应的spring data elasticsearch版本是4.2.x。

准备工作

  • CSS集群处于可用状态。
  • 确保运行Java代码的服务器与CSS集群的网络是互通的。
  • 根据集群选择的网络配置方式,获取集群的访问地址,具体操作请参见网络配置
  • 确认服务器已安装JDK1.8,JDK1.8官网下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
  • 创建SpringBoot项目。
  • 引入Java依赖。

    其中7.10.2为Elasticsearch Java客户端的版本号。

    • Maven方式引入:
      <parent>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-parent</artifactId>
          <version>2.5.5</version>
      </parent>
      <dependencies>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
          </dependency>
          <dependency>
              <groupId>org.elasticsearch.client</groupId>
              <artifactId>elasticsearch-rest-high-level-client</artifactId>
              <version>7.10.2</version>
          </dependency>
      </dependencies>

通过Spring Boot接入HTTP集群

该场景适用于连接非安全模式的集群或是安全模式+HTTP协议的集群。

配置文件:

1
2
3
4
elasticsearch.url=host1:9200,host2:9200
//非安全集群不用配置如下两行。
elasticsearch.username=username
elasticsearch.password=password
表1 参数说明

参数

描述

host

Elasticsearch集群的访问地址。

username

访问集群的用户名。

password

用户名对应的密码。

配置代码:

  • com.xxx为项目目录,例如com.company.project。
  • com.xxx.repository为仓库目录,通过extends org.springframework.data.elasticsearch.repository.ElasticsearchRepository进行具体定义。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.xxx.configuration;

import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.RestClients;
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;

@Configuration
@EnableElasticsearchRepositories(basePackages = "com.xxx.repository")
@ComponentScan(basePackages = "com.xxx")
public class Config extends AbstractElasticsearchConfiguration {

    @Value("${elasticsearch.url}")
    public String elasticsearchUrl;

    //非安全集群不用配置如下两个参数。
    @Value("${elasticsearch.username}")
    public String elasticsearchUsername;

    @Value("${elasticsearch.password}")
    public String elasticsearchPassword;

    @Override
    @Bean
    public RestHighLevelClient elasticsearchClient() {
        final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
            .connectedTo(StringHostParse(elasticsearchUrl))
            //非安全集群无需配置withBasicAuth。
            .withBasicAuth(elasticsearchUsername, elasticsearchPassword)
            .build();

        return RestClients.create(clientConfiguration).rest();
    }

    private String[] StringHostParse(String hostAndPorts) {
        return hostAndPorts.split(",");
    }
}

使用Spring Boot接入HTTPS集群(不使用安全证书)

该场景适用于不使用安全证书连接安全模式+HTTPS协议的集群。

配置文件:

1
2
3
elasticsearch.url=host1:9200,host2:9200
elasticsearch.username=username
elasticsearch.password=password
表2 参数说明

参数

描述

host

Elasticsearch集群的访问地址。

username

访问集群的用户名。

password

用户名对应的密码。

配置代码:

  • com.xxx为项目目录,例如com.company.project。
  • com.xxx.repository为仓库目录,通过extends org.springframework.data.elasticsearch.repository.ElasticsearchRepository进行具体定义。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package com.xxx.configuration;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.RestClients;
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
@Configuration
@EnableElasticsearchRepositories(basePackages = "com.xxx.repository")
@ComponentScan(basePackages = "com.xxx")
public class Config extends AbstractElasticsearchConfiguration {
    @Value("${elasticsearch.url}")
    public String elasticsearchUrl;
    @Value("${elasticsearch.username}")
    public String elasticsearchUsername;
    @Value("${elasticsearch.password}")
    public String elasticsearchPassword;
    @Override
    @Bean
    public RestHighLevelClient elasticsearchClient() {
        SSLContext sc = null;
        try {
            sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new SecureRandom());
        } catch (KeyManagementException | NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
            .connectedTo(StringHostParse(elasticsearchUrl))
            .usingSsl(sc, new NullHostNameVerifier())
            .withBasicAuth(elasticsearchUsername, elasticsearchPassword)
            .build();
        return RestClients.create(clientConfiguration).rest();
    }
    private String[] StringHostParse(String hostAndPorts) {
        return hostAndPorts.split(",");
    }
    public static TrustManager[] trustAllCerts = new TrustManager[] {
        new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }
            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        }
    };
    public static class NullHostNameVerifier implements HostnameVerifier {
        @Override
        public boolean verify(String arg0, SSLSession arg1) {
            return true;
        }
    }
}

使用Spring Boot接入HTTPS集群(使用安全证书)

该场景适用于使用安全证书连接安全模式+HTTPS协议的集群。

  1. 获取安全证书(CloudSearchService.cer)。
    1. 登录云搜索服务控制台。
    2. 选择“集群管理”进入集群列表。
    3. 单击对应集群的名称,进入集群基本信息页面。
    4. “基本信息”页面,单击“HTTPS访问”后面的“下载证书”
      图1 下载证书
  2. 转换安全证书(CloudSearchService.cer)。将下载的安全证书上传到客户端机器上,使用keytool工具将“.cer”证书转换成Java可以读取的“.jks”证书格式。
    • 在Linux系统中,执行如下命令转换证书。
      keytool -import -alias newname -keystore ./truststore.jks -file ./CloudSearchService.cer 
    • 在Windows系统中,执行如下命令转换证书。
      keytool -import -alias newname -keystore .\truststore.jks -file .\CloudSearchService.cer

    其中,newname是由用户自定义的证书名称。

    该命令执行后,会提示设置证书密码,并确认密码。请保存该密码,后续接入集群会使用。

  3. application.properties配置文件:
    1
    2
    3
    elasticsearch.url=host1:9200,host2:9200
    elasticsearch.username=username
    elasticsearch.password=password
    
    表3 参数说明

    参数

    描述

    host

    Elasticsearch集群的访问地址。

    username

    访问集群的用户名。

    password

    用户名对应的密码。

  4. 配置代码:
    • com.xxx为项目目录,例如com.company.project。
    • com.xxx.repository为仓库目录,通过extends org.springframework.data.elasticsearch.repository.ElasticsearchRepository进行具体定义。
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    package com.xxx.configuration;
    import org.elasticsearch.client.RestHighLevelClient;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.elasticsearch.client.ClientConfiguration;
    import org.springframework.data.elasticsearch.client.RestClients;
    import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
    import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.security.KeyStore;
    import java.security.SecureRandom;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    import javax.net.ssl.HostnameVerifier;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSession;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.TrustManagerFactory;
    import javax.net.ssl.X509TrustManager;
    @Configuration
    @EnableElasticsearchRepositories(basePackages = "com.xxx.repository")
    @ComponentScan(basePackages = "com.xxx")
    public class Config extends AbstractElasticsearchConfiguration {
        @Value("${elasticsearch.url}")
        public String elasticsearchUrl;
        @Value("${elasticsearch.username}")
        public String elasticsearchUsername;
        @Value("${elasticsearch.password}")
        public String elasticsearchPassword;
        @Override
        @Bean
        public RestHighLevelClient elasticsearchClient() {
            SSLContext sc = null;
            try {
                TrustManager[] tm = {new MyX509TrustManager(cerFilePath, cerPassword)};
                sc = SSLContext.getInstance("SSL", "SunJSSE");
                sc.init(null, tm, new SecureRandom());
            } catch (Exception e) {
                e.printStackTrace();
            }
            final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo(StringHostParse(elasticsearchUrl))
                .usingSsl(sc, new NullHostNameVerifier())
                .withBasicAuth(elasticsearchUsername, elasticsearchPassword)
                .build();
            return RestClients.create(clientConfiguration).rest();
        }
    
        private String[] StringHostParse(String hostAndPorts) {
            return hostAndPorts.split(",");
        }
    
        public static class MyX509TrustManager implements X509TrustManager {
            X509TrustManager sunJSSEX509TrustManager;
            MyX509TrustManager(String cerFilePath, String cerPassword) throws Exception {
                File file = new File(cerFilePath);
                if (!file.isFile()) {
                    throw new Exception("Wrong Certification Path");
                }
                System.out.println("Loading KeyStore " + file + "...");
                InputStream in = new FileInputStream(file);
                KeyStore ks = KeyStore.getInstance("JKS");
                ks.load(in, cerPassword.toCharArray());
                TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509", "SunJSSE");
                tmf.init(ks);
                TrustManager[] tms = tmf.getTrustManagers();
                for (TrustManager tm : tms) {
                    if (tm instanceof X509TrustManager) {
                        sunJSSEX509TrustManager = (X509TrustManager) tm;
                        return;
                    }
                }
                throw new Exception("Couldn't initialize");
            }
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }
            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        }
        public static class NullHostNameVerifier implements HostnameVerifier {
            @Override
            public boolean verify(String arg0, SSLSession arg1) {
                return true;
            }
        }
    }
    

    其中,cerFilePathcerPassword是生成的.jks证书的存放路径及其密码。