
# 通过RestLowLevelClient接入集群
在使用OpenSearch进行数据查询和管理时，用户可能会遇到使用High Level REST Client无法满足特定需求的情况。例如，当需要执行复杂的自定义请求时，High Level REST Client的限制可能导致无法实现。这时，可以考虑使用Low Level REST Client，它对OpenSearch的API进行了封装，用户只需要构造对应的结构即可对OpenSearch集群进行访问。使用Low Level REST Client发送请求时需要自定义请求结构，使用上更为灵活，能满足所有OpenSearch支持的请求格式，例如GET、POST、DELETE、HEAD等。
使用Low Level REST Client访问OpenSearch集群有2种方式：
- 直接创建RestLowLevelClient。
- 通过创建RestHighLevelClient再调用getLowLevelClient()获取RestLowLevelClient，即使用"RestHighLevelClient.getLowLevelClient()"方式获取RestLowLevelClient。
如何选择合适的访问方式以满足特定需求？建议根据实际需求选择：如果需要高度自定义的请求，直接创建RestLowLevelClient；如果已经在使用RestHighLevelClient，可以通过调用getLowLevelClient()方法获取RestLowLevelClient，以减少代码复杂度。
#### 前提条件
- OpenSearch集群处于可用状态。
- 运行Java代码的服务器与OpenSearch集群之间网络互通。
- 根据集群的网络配置方式，获取集群的访问地址，操作指导请参见[获取集群访问地址](https://support.huaweicloud.com/usermanual-css/css_01_0289.html#ZH-CN_TOPIC_0000001992165561__zh-cn_topic_0000001975823337_section855085010198)。
- 确认服务器已安装Java，要求JDK版本为11及以上，JDK11官网下载地址：[Java Archive Downloads](https://www.oracle.com/java/technologies/javase/jdk11-archive-downloads.html)。
 
#### 引入依赖
在运行Java代码的服务器中引入Java依赖。
CSS服务支持使用Elasticsearch 7.10.2 Java客户端连接OpenSearch集群，但是为确保更好的兼容性，建议使用与OpenSearch集群同版本的OpenSearch Java客户端连接OpenSearch集群。
可以根据实际使用的Java客户端类型选择参考示例。
- 场景一（推荐）：使用OpenSearch Java客户端访问OpenSearch集群，通过Maven方式引入apache版本。 使用时需要将1.3.6替换为实际Java客户端的版本号：
  ```
  <dependency>
      <groupId>org.opensearch.client</groupId>
      <artifactId>opensearch-rest-high-level-client</artifactId>
      <version>1.3.6</version>
  </dependency>
  ```
  
- 场景二：使用Elasticsearch 7.10.2 Java客户端访问OpenSearch集群，通过Maven方式引入apache版本。
  ```
  <dependency>
  <groupId>org.elasticsearch.client</groupId>
  <artifactId>elasticsearch-rest-high-level-client</artifactId>
  <version>7.10.2</version>
  </dependency>
  <dependency>
      <groupId>org.elasticsearch</groupId>
      <artifactId>elasticsearch</artifactId>
      <version>7.10.2</version>
  </dependency>
  ```
  
 
#### 接入集群
当使用不同类型的Java客户端访问不同安全类型的OpenSearch集群时，示例代码会有差异，请根据实际业务场景选择参考文档。
表1接入集群的场景介绍 
| Java客户端              | Low Level REST Client获取方式                                               | OpenSearch集群安全类型                                                         | 是否加载安全证书 | 参考文档                                                                                                |
|:---|:---|:---|:---|:---|
| OpenSearch           | 直接创建Low Level REST Client                                               | 非安全模式                                                                    | -        | [OpenSearch RestLowLevelClient连接非安全集群]            |
| OpenSearch           | 直接创建Low Level REST Client                                               | 安全模式+HTTP协议 安全模式+HTTPS协议     | 否        | [OpenSearch RestLowLevelClient连接安全集群（无证书）]     |
| OpenSearch           | 直接创建Low Level REST Client                                               | 安全模式+HTTPS协议                                                             | 是        | [OpenSearch RestLowLevelClient连接安全集群（加载证书）]    |
| OpenSearch           | 通过创建High Level REST Client再调用getLowLevelClient()获取Low Level REST Client | 非安全模式                                                                    | -        | [OpenSearch High Level Client连接非安全集群]           |
| OpenSearch           | 通过创建High Level REST Client再调用getLowLevelClient()获取Low Level REST Client | 安全模式+HTTP协议 安全模式+HTTPS协议 | 否        | [OpenSearch RestHighLevelClient连接安全集群（无证书）]     |
| OpenSearch           | 通过创建High Level REST Client再调用getLowLevelClient()获取Low Level REST Client | 安全模式+HTTPS协议                                                             | 是        | [OpenSearch RestHighLevelClient连接安全集群（加载证书）]  |
| Elasticsearch 7.10.2 | 直接创建Low Level REST Client                                               | 非安全模式                                                                    | -        | [Elasticsearch RestLowLevelClient连接非安全集群]       |
| Elasticsearch 7.10.2 | 直接创建Low Level REST Client                                               | 安全模式+HTTP协议 安全模式+HTTPS协议    | 否        | [Elasticsearch RestLowLevelClient连接安全集群（无证书）]   |
| Elasticsearch 7.10.2 | 直接创建Low Level REST Client                                               | 安全模式+HTTPS协议                                                             | 是        | [Elasticsearch RestLowLevelClient连接安全集群（加载证书）]   |
| Elasticsearch 7.10.2 | 通过创建High Level REST Client再调用getLowLevelClient()获取Low Level REST Client | 非安全模式                                                                    | -        | [Elasticsearch RestHighLevelClient连接非安全集群]    |
| Elasticsearch 7.10.2 | 通过创建High Level REST Client再调用getLowLevelClient()获取Low Level REST Client | 安全模式+HTTP协议 安全模式+HTTPS协议  | 否        | [Elasticsearch RestHighLevelClient连接安全集群（无证书）] |
| Elasticsearch 7.10.2 | 通过创建High Level REST Client再调用getLowLevelClient()获取Low Level REST Client | 安全模式+HTTPS协议                                                             | 是        | [Elasticsearch RestHighLevelClient连接安全集群（加载证书）] |
   
 #### OpenSearch RestLowLevelClient连接非安全集群
使用OpenSearch RestLowLevelClient连接非安全模式的OpenSearch集群，并查询索引"test"是否存在。代码示例如下：
```
import org.apache.http.HttpHost;
import org.opensearch.client.Request;
import org.opensearch.client.Response;
import org.opensearch.client.RestClient;
import org.opensearch.client.RestClientBuilder;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
public class RestLowLevelClientExample {
    public static void main(String[] args) throws IOException {
        List<String> host = Arrays.asList("{集群访问地址}");
        RestClientBuilder builder = RestClient.builder(constructHttpHosts(host, 9200, "http"));
        /**
         * 创建Rest Low Level Client
         */
        RestClient lowLevelClient = builder.build();
        /**
         * 查询test索引是否存在。当索引存在时返回200，不存在时返回404
         */
        Request request = new Request("HEAD", "/test");
        Response response = lowLevelClient.performRequest(request);
        System.out.println(response.getStatusLine().getStatusCode());
        lowLevelClient.close();
    }
    /**
     * constructHttpHosts函数转换host集群节点IP列表
     */
    public static HttpHost[] constructHttpHosts(List<String> host, int port, String protocol) {
        return host.stream().map(p -> new HttpHost(p, port, protocol)).toArray(HttpHost[]::new);
    }
}
```
该示例代码为判断集群是否存在test索引，当返回"200"（索引存在）或"404"（索引不存在）时，表示正常返回查询结果，集群连接成功。
 #### OpenSearch RestLowLevelClient连接安全集群（无证书）
使用OpenSearch RestLowLevelClient，在不加载安全证书的情况下连接安全模式的OpenSearch集群（支持HTTP协议或HTTPS协议），查询索引"test"是否存在。代码示例如下：
```
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;
import org.apache.http.protocol.HttpContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.opensearch.client.Request;
import org.opensearch.client.Response;
import org.opensearch.client.RestClient;
import org.opensearch.client.RestClientBuilder;
import org.opensearch.common.Nullable;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
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;
public class RestLowLevelClientExample {
    /**
     * 创建客户端的类，定义create函数用于创建客户端
     */
    public static RestClient create(List<String> host, int port, String protocol, int connectTimeout, int connectionRequestTimeout, int socketTimeout,  String username, String password) throws IOException {
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
        SSLContext sc = null;
        try {
            sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new SecureRandom());
        } catch (KeyManagementException | NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        SSLIOSessionStrategy sessionStrategy = new SSLIOSessionStrategy(sc, new NullHostNameVerifier());
        SecuredHttpClientConfigCallback httpClientConfigCallback = new SecuredHttpClientConfigCallback(sessionStrategy,
            credentialsProvider);
        RestClientBuilder builder = RestClient.builder(constructHttpHosts(host, port, protocol))
            .setRequestConfigCallback(requestConfig -> requestConfig.setConnectTimeout(connectTimeout)
                .setConnectionRequestTimeout(connectionRequestTimeout)
                .setSocketTimeout(socketTimeout))
            .setHttpClientConfigCallback(httpClientConfigCallback);
        final RestClient client = builder.build();
        logger.info("opensearch rest client build success {} ", client);
        return client;
    }
    /**
     * constructHttpHosts函数转换host集群节点IP列表
     */
    public static HttpHost[] constructHttpHosts(List<String> host, int port, String protocol) {
        return host.stream().map(p -> new HttpHost(p, port, protocol)).toArray(HttpHost[]::new);
    }
    /**
     * trustAllCerts忽略证书配置
     */
    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;
            }
        }
    };
    /**
     * CustomConnectionKeepAliveStrategy函数设置连接的保活时间，主要应对大量短连接的情况和数据请求不高的场景
     */
    public static class CustomConnectionKeepAliveStrategy extends DefaultConnectionKeepAliveStrategy {
        public static final CustomConnectionKeepAliveStrategy INSTANCE = new CustomConnectionKeepAliveStrategy();
        private CustomConnectionKeepAliveStrategy() {
            super();
        }
        /**
         * 最大Keep-Alive的时间（分钟）
         * 这里默认为10分钟，可以根据实际情况设置。可以观察客户端机器状态为TIME_WAIT的TCP连接数，如果太多，可以增大此值
         */
        private final long MAX_KEEP_ALIVE_MINUTES = 10;
        @Override
        public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
            long keepAliveDuration = super.getKeepAliveDuration(response, context);
            // <0 为无限期keepalive
            // 将无限期替换成一个默认的时间
            if (keepAliveDuration < 0) {
                return TimeUnit.MINUTES.toMillis(MAX_KEEP_ALIVE_MINUTES);
            }
            return keepAliveDuration;
        }
    }
    private static final Logger logger = LogManager.getLogger(RestLowLevelClientExample.class);
    static class SecuredHttpClientConfigCallback implements RestClientBuilder.HttpClientConfigCallback {
        @Nullable
        private final CredentialsProvider credentialsProvider;
        /**
         * The {@link SSLIOSessionStrategy} for all requests to enable SSL / TLS encryption.
         */
        private final SSLIOSessionStrategy sslStrategy;
        /**
         * Create a new {@link SecuredHttpClientConfigCallback}.
         *
         * @param credentialsProvider The credential provider, if a username/password have been supplied
         * @param sslStrategy         The SSL strategy, if SSL / TLS have been supplied
         * @throws NullPointerException if {@code sslStrategy} is {@code null}
         */
        SecuredHttpClientConfigCallback(final SSLIOSessionStrategy sslStrategy,
            @Nullable final CredentialsProvider credentialsProvider) {
            this.sslStrategy = Objects.requireNonNull(sslStrategy);
            this.credentialsProvider = credentialsProvider;
        }
        /**
         * Get the {@link CredentialsProvider} that will be added to the HTTP client.
         *
         * @return Can be {@code null}.
         */
        @Nullable
        CredentialsProvider getCredentialsProvider() {
            return credentialsProvider;
        }
        /**
         * Get the {@link SSLIOSessionStrategy} that will be added to the HTTP client.
         *
         * @return Never {@code null}.
         */
        SSLIOSessionStrategy getSSLStrategy() {
            return sslStrategy;
        }
        /**
         * Sets the {@linkplain HttpAsyncClientBuilder#setDefaultCredentialsProvider(CredentialsProvider) credential provider},
         *
         * @param httpClientBuilder The client to configure.
         * @return Always {@code httpClientBuilder}.
         */
        @Override
        public HttpAsyncClientBuilder customizeHttpClient(final HttpAsyncClientBuilder httpClientBuilder) {
            // enable SSL / TLS
            httpClientBuilder.setSSLStrategy(sslStrategy);
            // enable user authentication
            if (credentialsProvider != null) {
                httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
            }
            return httpClientBuilder;
        }
    }
    public static class NullHostNameVerifier implements HostnameVerifier {
        @Override
        public boolean verify(String arg0, SSLSession arg1) {
            return true;
        }
    }
    /**
     * main函数参考如下，调用create函数创建Rest Low Level Client客户端，查询test索引是否存在
     */
    public static void main(String[] args) throws IOException {
        RestClient lowLevelClient = create(Arrays.asList("xxx.xxx.xxx.xxx", "xxx.xxx.xxx.xxx"), 9200, "http", 30000, 30000, 30000, "username", "password");
        Request request = new Request("HEAD", "/test");
        Response response = lowLevelClient.performRequest(request);
        System.out.println(response.getStatusLine().getStatusCode());
        lowLevelClient.close();
    }
}
```
表2函数中的变量说明 
| 参数                       | 描述                               |
|:---|:---|
| host                     | 集群访问地址，当存在多个IP地址时，中间用","隔开。      |
| port                     | 集群的连接端口，默认是"9200"。               |
| protocol                 | 连接协议，"http"或者"https"，根据集群实际情况填写。 |
| connectTimeout           | 连接超时时间（毫秒）。                      |
| connectionRequestTimeout | socket连接请求超时时间（毫秒）。              |
| socketTimeout            | socket请求超时时间（毫秒）。                |
| username                 | 访问集群的用户名。                        |
| password                 | 用户名对应的密码。                        |
   
该示例代码为判断集群是否存在test索引，当返回"200"（索引存在）或"404"（索引不存在）时，表示正常返回查询结果，集群连接成功。
 #### OpenSearch RestLowLevelClient连接安全集群（加载证书）
使用OpenSearch RestLowLevelClient，在加载安全证书的情况下连接安全模式+HTTPS协议的OpenSearch集群，查询索引"test"是否存在。代码示例如下：
![](https://support.huaweicloud.com/usermanual-css/public_sys-resources/caution_3.0-zh-cn.png)
连接安全模式+HTTPS协议的OpenSearch集群需要先提前准备好安全证书，操作指导请参见[获取并上传安全证书]。
```
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.opensearch.client.Request;
import org.opensearch.client.Response;
import org.opensearch.client.RestClient;
import org.opensearch.client.RestClientBuilder;
import org.opensearch.common.Nullable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import javax.net.ssl.SSLContext;import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
public class RestLowLevelClientExample {
    private static final Logger logger = LogManager.getLogger(RestLowLevelClientExample.class);
    /**
     * 创建客户端的类，定义create函数用于创建客户端
     */
    public static RestClient create(List<String> host, int port, String protocol, int connectTimeout, int connectionRequestTimeout, int socketTimeout, String username, String password, String certFilePath, String certPassword) throws IOException {
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
        SSLContext sc = null;
        try {
            TrustManager[] tm = {new MyX509TrustManager(certFilePath, certPassword)};
            sc = SSLContext.getInstance("SSL", "SunJSSE");
            //也可以使用SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
            sc.init(null, tm, new SecureRandom());
        } catch (Exception e) {
            e.printStackTrace();
        }
        SSLIOSessionStrategy sessionStrategy = new SSLIOSessionStrategy(sc, new NoopHostnameVerifier());
        SecuredHttpClientConfigCallback httpClientConfigCallback = new SecuredHttpClientConfigCallback(sessionStrategy,
            credentialsProvider);
        RestClientBuilder builder = RestClient.builder(constructHttpHosts(host, port, protocol))
            .setRequestConfigCallback(requestConfig -> requestConfig.setConnectTimeout(connectTimeout)
                .setConnectionRequestTimeout(connectionRequestTimeout)
                .setSocketTimeout(socketTimeout))
            .setHttpClientConfigCallback(httpClientConfigCallback);
        final RestClient client = builder.build();
        logger.info("opensearch rest client build success {} ", client);
        return client;
    }
    /**
     * constructHttpHosts函数转换host集群节点IP列表
     */
    public static HttpHost[] constructHttpHosts(List<String> host, int port, String protocol) {
        return host.stream().map(p -> new HttpHost(p, port, protocol)).toArray(HttpHost[]::new);}
    static class SecuredHttpClientConfigCallback implements RestClientBuilder.HttpClientConfigCallback {
        @Nullable
        private final CredentialsProvider credentialsProvider;
        private final SSLIOSessionStrategy sslStrategy;
        SecuredHttpClientConfigCallback(final SSLIOSessionStrategy sslStrategy,
            @Nullable final CredentialsProvider credentialsProvider) {
            this.sslStrategy = Objects.requireNonNull(sslStrategy);
            this.credentialsProvider = credentialsProvider;
        }
        @Nullable
        CredentialsProvider getCredentialsProvider() {
            return credentialsProvider;
        }
        SSLIOSessionStrategy getSSLStrategy() {
            return sslStrategy;
        }
        @Override
        public HttpAsyncClientBuilder customizeHttpClient(final HttpAsyncClientBuilder httpClientBuilder) {
            httpClientBuilder.setSSLStrategy(sslStrategy);
            if (credentialsProvider != null) {
                httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
            }
            return httpClientBuilder;
        }}
    public static class MyX509TrustManager implements X509TrustManager {
        X509TrustManager sunJSSEX509TrustManager;
        MyX509TrustManager(String certFilePath, String certPassword) throws Exception {
            File file = new File(certFilePath);
            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, certPassword.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];
        }
    }
    /**
     * main函数参考如下，调用create函数创建Rest Low Level Client，查询test索引是否存在
     */
    public static void main(String[] args) throws IOException {
        RestClient lowLevelClient = create(Arrays.asList("xxx.xxx.xxx.xxx", "xxx.xxx.xxx.xxx"), 9200, "https", 30000, 30000, 30000, "username", "password", "certFilePath", "certPassword");
        Request request = new Request("HEAD", "test");
        Response response = lowLevelClient.performRequest(request);
        System.out.println(response.getStatusLine().getStatusCode());
        lowLevelClient.close();
    }
}
```
表3函数中的参数说明 
| 参数                       | 描述                          |
|:---|:---|
| host                     | 集群访问地址，当存在多个IP地址时，中间用","隔开。 |
| port                     | 集群的连接端口，默认是"9200"。          |
| protocol                 | 连接协议，此处填写"https"。           |
| connectTimeout           | 连接超时时间（毫秒）。                 |
| connectionRequestTimeout | socket连接请求超时时间（毫秒）。         |
| socketTimeout            | socket请求超时时间（毫秒）。           |
| username                 | 访问集群的用户名。                   |
| password                 | 用户名对应的密码。                   |
| certFilePath             | 安全证书路径。                     |
| certPassword             | 安全证书密码。                     |
   
该示例代码为判断集群是否存在test索引，当返回"200"（索引存在）或"404"（索引不存在）时，表示正常返回查询结果，集群连接成功。
 #### OpenSearch RestHighLevelClient连接非安全集群
使用OpenSearch RestHighLevelClient调用"getLowLevelClient()"获取RestLowLevelClient，再连接非安全模式的OpenSearch集群，并查询索引"test"是否存在。代码示例如下：
```
import org.apache.http.HttpHost;
import org.opensearch.client.Request;
import org.opensearch.client.Response;
import org.opensearch.client.RestClient;
import org.opensearch.client.RestClientBuilder;
import org.opensearch.client.RestHighLevelClient;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
public class RestLowLevelClientExample {
    public static void main(String[] args) throws IOException {
        List<String> host = Arrays.asList("{集群访问地址}");
        RestClientBuilder builder = RestClient.builder(constructHttpHosts(host, 9200, "http"));
        final RestHighLevelClient restHighLevelClient = new RestHighLevelClient(builder);
        /**
         * 创建High Level Client再调用getLowLevelClient()获取Low Level Client，即client创建仅下面这一行代码存在差别
         */
        final RestClient lowLevelClient = restHighLevelClient.getLowLevelClient();
        /**
         * 查询test索引是否存在。当索引存在时返回200，不存在时返回404
         */
        Request request = new Request("HEAD", "/test");
        Response response = lowLevelClient.performRequest(request);
        System.out.println(response.getStatusLine().getStatusCode());
        lowLevelClient.close();
    }
    /**
     * constructHttpHosts函数转换host集群节点IP列表
     */
    public static HttpHost[] constructHttpHosts(List<String> host, int port, String protocol) {
        return host.stream().map(p -> new HttpHost(p, port, protocol)).toArray(HttpHost[]::new);
    }
}
```
该示例代码为判断集群是否存在test索引，当返回"200"（索引存在）或"404"（索引不存在）时，表示正常返回查询结果，集群连接成功。
 #### OpenSearch RestHighLevelClient连接安全集群（无证书）
使用OpenSearch RestHighLevelClient调用"getLowLevelClient()"获取RestLowLevelClient，在不加载安全证书的情况下连接安全模式的OpenSearch集群（支持HTTP协议或HTTPS协议），查询索引"test"是否存在。代码示例如下：
```
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;
import org.apache.http.protocol.HttpContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.opensearch.client.Request;
import org.opensearch.client.Response;
import org.opensearch.client.RestClient;
import org.opensearch.client.RestClientBuilder;
import org.opensearch.client.RestHighLevelClient;
import org.opensearch.common.Nullable;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
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;
public class RestLowLevelClientExample {
    /**
     * 创建客户端的类，定义create函数用于创建客户端
     */
    public static RestHighLevelClient create(List<String> host, int port, String protocol, int connectTimeout, int connectionRequestTimeout, int socketTimeout,  String username, String password) throws IOException {
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
        SSLContext sc = null;
        try {
            sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new SecureRandom());
        } catch (KeyManagementException | NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        SSLIOSessionStrategy sessionStrategy = new SSLIOSessionStrategy(sc, new NullHostNameVerifier());
        SecuredHttpClientConfigCallback httpClientConfigCallback = new SecuredHttpClientConfigCallback(sessionStrategy,
            credentialsProvider);
        RestClientBuilder builder = RestClient.builder(constructHttpHosts(host, port, protocol))
            .setRequestConfigCallback(requestConfig -> requestConfig.setConnectTimeout(connectTimeout)
                .setConnectionRequestTimeout(connectionRequestTimeout)
                .setSocketTimeout(socketTimeout))
            .setHttpClientConfigCallback(httpClientConfigCallback);
        final RestHighLevelClient client = new RestHighLevelClient(builder);
        logger.info("opensearch rest client build success {} ", client);
        return client;
    }
    /**
     * constructHttpHosts函数转换host集群节点IP列表
     */
    public static HttpHost[] constructHttpHosts(List<String> host, int port, String protocol) {
        return host.stream().map(p -> new HttpHost(p, port, protocol)).toArray(HttpHost[]::new);
    }
    /**
     * trustAllCerts忽略证书配置
     */
    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;
            }
        }
    };
    /**
     * CustomConnectionKeepAliveStrategy函数设置连接的保活时间，主要应对大量短连接的情况和数据请求不高的场景
     */
    public static class CustomConnectionKeepAliveStrategy extends DefaultConnectionKeepAliveStrategy {
        public static final CustomConnectionKeepAliveStrategy INSTANCE = new CustomConnectionKeepAliveStrategy();
        private CustomConnectionKeepAliveStrategy() {
            super();
        }
        /**
         * 最大Keep-Alive的时间（分钟）
         * 这里默认为10分钟，可以根据实际情况设置。可以观察客户端机器状态为TIME_WAIT的TCP连接数，如果太多，可以增大此值
         */
        private final long MAX_KEEP_ALIVE_MINUTES = 10;
        @Override
        public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
            long keepAliveDuration = super.getKeepAliveDuration(response, context);
            // <0 为无限期keep-alive
            // 将无限期替换成一个默认的时间
            if (keepAliveDuration < 0) {
                return TimeUnit.MINUTES.toMillis(MAX_KEEP_ALIVE_MINUTES);
            }
            return keepAliveDuration;
        }
    }
    private static final Logger logger = LogManager.getLogger(RestLowLevelClientExample.class);
    static class SecuredHttpClientConfigCallback implements RestClientBuilder.HttpClientConfigCallback {
        @Nullable
        private final CredentialsProvider credentialsProvider;
        /**
         * The {@link SSLIOSessionStrategy} for all requests to enable SSL / TLS encryption.
         */
        private final SSLIOSessionStrategy sslStrategy;
        /**
         * Create a new {@link SecuredHttpClientConfigCallback}.
         *
         * @param credentialsProvider The credential provider, if a username/password have been supplied
         * @param sslStrategy         The SSL strategy, if SSL / TLS have been supplied
         * @throws NullPointerException if {@code sslStrategy} is {@code null}
         */
        SecuredHttpClientConfigCallback(final SSLIOSessionStrategy sslStrategy,
            @Nullable final CredentialsProvider credentialsProvider) {
            this.sslStrategy = Objects.requireNonNull(sslStrategy);
            this.credentialsProvider = credentialsProvider;
        }
        /**
         * Get the {@link CredentialsProvider} that will be added to the HTTP client.
         *
         * @return Can be {@code null}.
         */
        @Nullable
        CredentialsProvider getCredentialsProvider() {
            return credentialsProvider;
        }
        /**
         * Get the {@link SSLIOSessionStrategy} that will be added to the HTTP client.
         *
         * @return Never {@code null}.
         */
        SSLIOSessionStrategy getSSLStrategy() {
            return sslStrategy;
        }
        /**
         * Sets the {@linkplain HttpAsyncClientBuilder#setDefaultCredentialsProvider(CredentialsProvider) credential provider},
         *
         * @param httpClientBuilder The client to configure.
         * @return Always {@code httpClientBuilder}.
         */
        @Override
        public HttpAsyncClientBuilder customizeHttpClient(final HttpAsyncClientBuilder httpClientBuilder) {
            // enable SSL / TLS
            httpClientBuilder.setSSLStrategy(sslStrategy);
            // enable user authentication
            if (credentialsProvider != null) {
                httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
            }
            return httpClientBuilder;
        }
    }
    public static class NullHostNameVerifier implements HostnameVerifier {
        @Override
        public boolean verify(String arg0, SSLSession arg1) {
            return true;
        }
    }
    /**
     * main函数参考如下，调用create函数创建High Level Client再调用getLowLevelClient()获取Low Level Client，并查询test索引是否存在
     */
    public static void main(String[] args) throws IOException {
        RestHighLevelClient client = create(Arrays.asList("xxx.xxx.xxx.xxx", "xxx.xxx.xxx.xxx"), 9200, "http", 30000, 30000, 30000, "username", "password");
        RestClient lowLevelClient = client.getLowLevelClient();
        Request request = new Request("HEAD", "test");
        Response response = lowLevelClient.performRequest(request);
        System.out.println(response.getStatusLine().getStatusCode());
        lowLevelClient.close();
    }
}
```
表4函数中的变量说明 
| 参数                       | 描述                               |
|:---|:---|
| host                     | 集群访问地址，当存在多个IP地址时，中间用","隔开。      |
| port                     | 集群的连接端口，默认是"9200"。               |
| protocol                 | 连接协议，"http"或者"https"，根据集群实际情况填写。 |
| connectTimeout           | 连接超时时间（毫秒）。                      |
| connectionRequestTimeout | socket连接请求超时时间（毫秒）。              |
| socketTimeout            | socket请求超时时间（毫秒）。                |
| username                 | 访问集群的用户名。                        |
| password                 | 用户名对应的密码。                        |
   
该示例代码为判断集群是否存在test索引，当返回"200"（索引存在）或"404"（索引不存在）时，表示正常返回查询结果，集群连接成功。
 #### OpenSearch RestHighLevelClient连接安全集群（加载证书）
使用OpenSearch RestHighLevelClient，在加载安全证书的情况下连接安全模式+HTTPS协议的OpenSearch集群，查询索引"test"是否存在。代码示例如下：
![](https://support.huaweicloud.com/usermanual-css/public_sys-resources/caution_3.0-zh-cn.png)
连接安全模式+HTTPS协议的OpenSearch集群需要先提前准备好安全证书，操作指导请参见[获取并上传安全证书]。
```
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.opensearch.action.admin.cluster.health.ClusterHealthRequest;
import org.opensearch.action.admin.cluster.health.ClusterHealthResponse;
import org.opensearch.client.Request;
import org.opensearch.client.RequestOptions;
import org.opensearch.client.Response;
import org.opensearch.client.RestClient;
import org.opensearch.client.RestClientBuilder;
import org.opensearch.client.RestHighLevelClient;
import org.opensearch.common.Nullable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
public class RestLowLevelClientExample {
    private static final Logger logger = LogManager.getLogger(RestLowLevelClientExample.class);
    /**
     * 创建客户端的类，定义create函数用于创建客户端
     */
    public static RestHighLevelClient create(List<String> host, int port, String protocol, int connectTimeout, int connectionRequestTimeout, int socketTimeout, String username, String password, String certFilePath, String certPassword) throws IOException {
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
        SSLContext sc = null;
        try {
            TrustManager[] tm = {new MyX509TrustManager(certFilePath, certPassword)};
            sc = SSLContext.getInstance("SSL", "SunJSSE");
            //也可以使用SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
            sc.init(null, tm, new SecureRandom());
        } catch (Exception e) {
            e.printStackTrace();
        }
        SSLIOSessionStrategy sessionStrategy = new SSLIOSessionStrategy(sc, new NoopHostnameVerifier());
        SecuredHttpClientConfigCallback httpClientConfigCallback = new SecuredHttpClientConfigCallback(sessionStrategy,
            credentialsProvider);
        RestClientBuilder builder = RestClient.builder(constructHttpHosts(host, port, protocol))
            .setRequestConfigCallback(requestConfig -> requestConfig.setConnectTimeout(connectTimeout)
                .setConnectionRequestTimeout(connectionRequestTimeout)
                .setSocketTimeout(socketTimeout))
            .setHttpClientConfigCallback(httpClientConfigCallback);
        final RestHighLevelClient client = new RestHighLevelClient(builder);
        logger.info("opensearch rest client build success {} ", client);
        ClusterHealthRequest request = new ClusterHealthRequest();
        ClusterHealthResponse response = client.cluster().health(request, RequestOptions.DEFAULT);
        logger.info("opensearch rest client health response {} ", response);
        return client;
    }
    /**
     * constructHttpHosts函数转换host集群节点IP列表
     */
    public static HttpHost[] constructHttpHosts(List<String> host, int port, String protocol) {
        return host.stream().map(p -> new HttpHost(p, port, protocol)).toArray(HttpHost[]::new);}
    static class SecuredHttpClientConfigCallback implements RestClientBuilder.HttpClientConfigCallback {
        @Nullable
        private final CredentialsProvider credentialsProvider;
        private final SSLIOSessionStrategy sslStrategy;
        SecuredHttpClientConfigCallback(final SSLIOSessionStrategy sslStrategy,
            @Nullable final CredentialsProvider credentialsProvider) {
            this.sslStrategy = Objects.requireNonNull(sslStrategy);
            this.credentialsProvider = credentialsProvider;
        }
        @Nullable
        CredentialsProvider getCredentialsProvider() {
            return credentialsProvider;
        }
        SSLIOSessionStrategy getSSLStrategy() {
            return sslStrategy;
        }
        @Override
        public HttpAsyncClientBuilder customizeHttpClient(final HttpAsyncClientBuilder httpClientBuilder) {
            httpClientBuilder.setSSLStrategy(sslStrategy);
            if (credentialsProvider != null) {
                httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
            }
            return httpClientBuilder;
        }}
    public static class MyX509TrustManager implements X509TrustManager {
        X509TrustManager sunJSSEX509TrustManager;
        MyX509TrustManager(String certFilePath, String certPassword) throws Exception {
            File file = new File(certFilePath);
            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, certPassword.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];
        }
    }
    /**
     * main函数参考如下，调用create函数创建High Level Client再调用getLowLevelClient()获取Low Level Client，并查询test索引是否存在
     */
    public static void main(String[] args) throws IOException {
        RestHighLevelClient client = create(Arrays.asList("xxx.xxx.xxx.xxx", "xxx.xxx.xxx.xxx"), 9200, "https", 30000, 30000, 30000, "username", "password", "certFilePath", "certPassword");
        RestClient lowLevelClient = client.getLowLevelClient();
        Request request = new Request("HEAD", "test");
        Response response = lowLevelClient.performRequest(request);
        System.out.println(response.getStatusLine().getStatusCode());
        lowLevelClient.close();
    }
}
```
表5函数中的参数说明 
| 参数                       | 描述                          |
|:---|:---|
| host                     | 集群访问地址，当存在多个IP地址时，中间用","隔开。 |
| port                     | 集群的连接端口，默认是"9200"。          |
| protocol                 | 连接协议，此处填写"https"。           |
| connectTimeout           | 连接超时时间（毫秒）。                 |
| connectionRequestTimeout | socket连接请求超时时间（毫秒）。         |
| socketTimeout            | socket请求超时时间（毫秒）。           |
| username                 | 访问集群的用户名。                   |
| password                 | 用户名对应的密码。                   |
| certFilePath             | 安全证书路径。                     |
| certPassword             | 安全证书密码。                     |
   
该示例代码为判断集群是否存在test索引，当返回"200"（索引存在）或"404"（索引不存在）时，表示正常返回查询结果，集群连接成功。
 #### Elasticsearch RestLowLevelClient连接非安全集群
使用Elasticsearch 7.10.2 RestLowLevelClient连接非安全模式的OpenSearch集群，并查询索引"test"是否存在。代码示例如下：
```
import org.apache.http.HttpHost;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
public class RestLowLevelClientExample {
    public static void main(String[] args) throws IOException {
        List<String> host = Arrays.asList("{集群访问地址}");
        RestClientBuilder builder = RestClient.builder(constructHttpHosts(host, 9200, "http"));
        /**
         * 创建Rest Low Level Client
         */
        RestClient lowLevelClient = builder.build();
        /**
         * 查询test索引是否存在。当索引存在时返回200，不存在时返回404
         */
        Request request = new Request("HEAD", "/test");
        Response response = lowLevelClient.performRequest(request);
        System.out.println(response.getStatusLine().getStatusCode());
        lowLevelClient.close();
    }
    /**
     * constructHttpHosts函数转换host集群节点IP列表
     */
    public static HttpHost[] constructHttpHosts(List<String> host, int port, String protocol) {
        return host.stream().map(p -> new HttpHost(p, port, protocol)).toArray(HttpHost[]::new);
    }
}
```
该示例代码为判断集群是否存在test索引，当返回"200"（索引存在）或"404"（索引不存在）时，表示正常返回查询结果，集群连接成功。
 #### Elasticsearch RestLowLevelClient连接安全集群（无证书）
使用Elasticsearch 7.10.2 RestLowLevelClient，在不加载安全证书的情况下连接安全模式的OpenSearch集群（支持HTTP协议或HTTPS协议），查询索引"test"是否存在。代码示例如下：
```
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;
import org.apache.http.protocol.HttpContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.common.Nullable;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
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;
public class RestLowLevelClientExample {
    /**
     * 创建客户端的类，定义create函数用于创建客户端
     */
    public static RestClient create(List<String> host, int port, String protocol, int connectTimeout, int connectionRequestTimeout, int socketTimeout,  String username, String password) throws IOException {
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
        SSLContext sc = null;
        try {
            sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new SecureRandom());
        } catch (KeyManagementException | NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        SSLIOSessionStrategy sessionStrategy = new SSLIOSessionStrategy(sc, new NullHostNameVerifier());
        SecuredHttpClientConfigCallback httpClientConfigCallback = new SecuredHttpClientConfigCallback(sessionStrategy,
            credentialsProvider);
        RestClientBuilder builder = RestClient.builder(constructHttpHosts(host, port, protocol))
            .setRequestConfigCallback(requestConfig -> requestConfig.setConnectTimeout(connectTimeout)
                .setConnectionRequestTimeout(connectionRequestTimeout)
                .setSocketTimeout(socketTimeout))
            .setHttpClientConfigCallback(httpClientConfigCallback);
        final RestClient client = builder.build();
        logger.info("es rest client build success {} ", client);
        return client;
    }
    /**
     * constructHttpHosts函数转换host集群节点IP列表
     */
    public static HttpHost[] constructHttpHosts(List<String> host, int port, String protocol) {
        return host.stream().map(p -> new HttpHost(p, port, protocol)).toArray(HttpHost[]::new);
    }
    /**
     * trustAllCerts忽略证书配置
     */
    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;
            }
        }
    };
    /**
     * CustomConnectionKeepAliveStrategy函数设置连接的保活时间，主要应对大量短连接的情况和数据请求不高的场景
     */
    public static class CustomConnectionKeepAliveStrategy extends DefaultConnectionKeepAliveStrategy {
        public static final CustomConnectionKeepAliveStrategy INSTANCE = new CustomConnectionKeepAliveStrategy();
        private CustomConnectionKeepAliveStrategy() {
            super();
        }
        /**
         * 最大Keep-Alive的时间（分钟）
         * 这里默认为10分钟，可以根据实际情况设置。可以观察客户端机器状态为TIME_WAIT的TCP连接数，如果太多，可以增大此值
         */
        private final long MAX_KEEP_ALIVE_MINUTES = 10;
        @Override
        public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
            long keepAliveDuration = super.getKeepAliveDuration(response, context);
            // <0 为无限期keep-alive
            // 将无限期替换成一个默认的时间
            if (keepAliveDuration < 0) {
                return TimeUnit.MINUTES.toMillis(MAX_KEEP_ALIVE_MINUTES);
            }
            return keepAliveDuration;
        }
    }
    private static final Logger logger = LogManager.getLogger(RestLowLevelClientExample.class);
    static class SecuredHttpClientConfigCallback implements RestClientBuilder.HttpClientConfigCallback {
        @Nullable
        private final CredentialsProvider credentialsProvider;
        /**
         * The {@link SSLIOSessionStrategy} for all requests to enable SSL / TLS encryption.
         */
        private final SSLIOSessionStrategy sslStrategy;
        /**
         * Create a new {@link SecuredHttpClientConfigCallback}.
         *
         * @param credentialsProvider The credential provider, if a username/password have been supplied
         * @param sslStrategy         The SSL strategy, if SSL / TLS have been supplied
         * @throws NullPointerException if {@code sslStrategy} is {@code null}
         */
        SecuredHttpClientConfigCallback(final SSLIOSessionStrategy sslStrategy,
            @Nullable final CredentialsProvider credentialsProvider) {
            this.sslStrategy = Objects.requireNonNull(sslStrategy);
            this.credentialsProvider = credentialsProvider;
        }
        /**
         * Get the {@link CredentialsProvider} that will be added to the HTTP client.
         *
         * @return Can be {@code null}.
         */
        @Nullable
        CredentialsProvider getCredentialsProvider() {
            return credentialsProvider;
        }
        /**
         * Get the {@link SSLIOSessionStrategy} that will be added to the HTTP client.
         *
         * @return Never {@code null}.
         */
        SSLIOSessionStrategy getSSLStrategy() {
            return sslStrategy;
        }
        /**
         * Sets the {@linkplain HttpAsyncClientBuilder#setDefaultCredentialsProvider(CredentialsProvider) credential provider},
         *
         * @param httpClientBuilder The client to configure.
         * @return Always {@code httpClientBuilder}.
         */
        @Override
        public HttpAsyncClientBuilder customizeHttpClient(final HttpAsyncClientBuilder httpClientBuilder) {
            // enable SSL / TLS
            httpClientBuilder.setSSLStrategy(sslStrategy);
            // enable user authentication
            if (credentialsProvider != null) {
                httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
            }
            return httpClientBuilder;
        }
    }
    public static class NullHostNameVerifier implements HostnameVerifier {
        @Override
        public boolean verify(String arg0, SSLSession arg1) {
            return true;
        }
    }
    /**
     * main函数参考如下，调用create函数创建Rest Low Level Client客户端，查询test索引是否存在
     */
    public static void main(String[] args) throws IOException {
        RestClient lowLevelClient = create(Arrays.asList("xxx.xxx.xxx.xxx", "xxx.xxx.xxx.xxx"), 9200, "http", 30000, 30000, 30000, "username", "password");
        Request request = new Request("HEAD", "/test");
        Response response = lowLevelClient.performRequest(request);
        System.out.println(response.getStatusLine().getStatusCode());
        lowLevelClient.close();
    }
}
```
表6函数中的变量说明 
| 参数                       | 描述                               |
|:---|:---|
| host                     | 集群访问地址，当存在多个IP地址时，中间用","隔开。      |
| port                     | 集群的连接端口，默认是"9200"。               |
| protocol                 | 连接协议，"http"或者"https"，根据集群实际情况填写。 |
| connectTimeout           | 连接超时时间（毫秒）。                      |
| connectionRequestTimeout | socket连接请求超时时间（毫秒）。              |
| socketTimeout            | socket请求超时时间（毫秒）。                |
| username                 | 访问集群的用户名。                        |
| password                 | 用户名对应的密码。                        |
   
该示例代码为判断集群是否存在test索引，当返回"200"（索引存在）或"404"（索引不存在）时，表示正常返回查询结果，集群连接成功。
 #### Elasticsearch RestLowLevelClient连接安全集群（加载证书）
使用Elasticsearch 7.10.2 RestLowLevelClient，在加载安全证书的情况下连接安全模式+HTTPS协议的OpenSearch集群，查询索引"test"是否存在。代码示例如下：
![](https://support.huaweicloud.com/usermanual-css/public_sys-resources/caution_3.0-zh-cn.png)
连接安全模式+HTTPS协议的OpenSearch集群需要先提前准备好安全证书，操作指导请参见[获取并上传安全证书]。
```
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.common.Nullable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import javax.net.ssl.SSLContext;import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
public class RestLowLevelClientExample {
    private static final Logger logger = LogManager.getLogger(RestLowLevelClientExample.class);
    /**
     * 创建客户端的类，定义create函数用于创建客户端
     */
    public static RestClient create(List<String> host, int port, String protocol, int connectTimeout, int connectionRequestTimeout, int socketTimeout, String username, String password, String certFilePath, String certPassword) throws IOException {
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
        SSLContext sc = null;
        try {
            TrustManager[] tm = {new MyX509TrustManager(certFilePath, certPassword)};
            sc = SSLContext.getInstance("SSL", "SunJSSE");
            //也可以使用SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
            sc.init(null, tm, new SecureRandom());
        } catch (Exception e) {
            e.printStackTrace();
        }
        SSLIOSessionStrategy sessionStrategy = new SSLIOSessionStrategy(sc, new NoopHostnameVerifier());
        SecuredHttpClientConfigCallback httpClientConfigCallback = new SecuredHttpClientConfigCallback(sessionStrategy,
            credentialsProvider);
        RestClientBuilder builder = RestClient.builder(constructHttpHosts(host, port, protocol))
            .setRequestConfigCallback(requestConfig -> requestConfig.setConnectTimeout(connectTimeout)
                .setConnectionRequestTimeout(connectionRequestTimeout)
                .setSocketTimeout(socketTimeout))
            .setHttpClientConfigCallback(httpClientConfigCallback);
        final RestClient client = builder.build();
        logger.info("es rest client build success {} ", client);
        return client;
    }
    /**
     * constructHttpHosts函数转换host集群节点IP列表
     */
    public static HttpHost[] constructHttpHosts(List<String> host, int port, String protocol) {
        return host.stream().map(p -> new HttpHost(p, port, protocol)).toArray(HttpHost[]::new);}
    static class SecuredHttpClientConfigCallback implements RestClientBuilder.HttpClientConfigCallback {
        @Nullable
        private final CredentialsProvider credentialsProvider;
        private final SSLIOSessionStrategy sslStrategy;
        SecuredHttpClientConfigCallback(final SSLIOSessionStrategy sslStrategy,
            @Nullable final CredentialsProvider credentialsProvider) {
            this.sslStrategy = Objects.requireNonNull(sslStrategy);
            this.credentialsProvider = credentialsProvider;
        }
        @Nullable
        CredentialsProvider getCredentialsProvider() {
            return credentialsProvider;
        }
        SSLIOSessionStrategy getSSLStrategy() {
            return sslStrategy;
        }
        @Override
        public HttpAsyncClientBuilder customizeHttpClient(final HttpAsyncClientBuilder httpClientBuilder) {
            httpClientBuilder.setSSLStrategy(sslStrategy);
            if (credentialsProvider != null) {
                httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
            }
            return httpClientBuilder;
        }}
    public static class MyX509TrustManager implements X509TrustManager {
        X509TrustManager sunJSSEX509TrustManager;
        MyX509TrustManager(String certFilePath, String certPassword) throws Exception {
            File file = new File(certFilePath);
            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, certPassword.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];
        }
    }
    /**
     * main函数参考如下，调用create函数创建Rest Low Level Client，查询test索引是否存在
     */
    public static void main(String[] args) throws IOException {
        RestClient lowLevelClient = create(Arrays.asList("xxx.xxx.xxx.xxx", "xxx.xxx.xxx.xxx"), 9200, "https", 30000, 30000, 30000, "username", "password", "certFilePath", "certPassword");
        Request request = new Request("HEAD", "test");
        Response response = lowLevelClient.performRequest(request);
        System.out.println(response.getStatusLine().getStatusCode());
        lowLevelClient.close();
    }
}
```
表7函数中的参数说明 
| 参数                       | 描述                          |
|:---|:---|
| host                     | 集群访问地址，当存在多个IP地址时，中间用","隔开。 |
| port                     | 集群的连接端口，默认是"9200"。          |
| protocol                 | 连接协议，此处填写"https"。           |
| connectTimeout           | 连接超时时间（毫秒）。                 |
| connectionRequestTimeout | socket连接请求超时时间（毫秒）。         |
| socketTimeout            | socket请求超时时间（毫秒）。           |
| username                 | 访问集群的用户名。                   |
| password                 | 用户名对应的密码。                   |
| certFilePath             | 安全证书路径。                     |
| certPassword             | 安全证书密码。                     |
   
该示例代码为判断集群是否存在test索引，当返回"200"（索引存在）或"404"（索引不存在）时，表示正常返回查询结果，集群连接成功。
 #### Elasticsearch RestHighLevelClient连接非安全集群
使用Elasticsearch 7.10.2 RestHighLevelClient调用"getLowLevelClient()"获取RestLowLevelClient，再连接非安全模式的OpenSearch集群，并查询索引"test"是否存在。代码示例如下：
```
import org.apache.http.HttpHost;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
public class RestLowLevelClientExample {
    public static void main(String[] args) throws IOException {
        List<String> host = Arrays.asList("{集群访问地址}");
        RestClientBuilder builder = RestClient.builder(constructHttpHosts(host, 9200, "http"));
        final RestHighLevelClient restHighLevelClient = new RestHighLevelClient(builder);
        /**
         * 创建High Level Client再调用getLowLevelClient()获取Low Level Client，即client创建仅下面这一行代码存在差别
         */
        final RestClient lowLevelClient = restHighLevelClient.getLowLevelClient();
        /**
         * 查询test索引是否存在。当索引存在时返回200，不存在时返回404
         */
        Request request = new Request("HEAD", "/test");
        Response response = lowLevelClient.performRequest(request);
        System.out.println(response.getStatusLine().getStatusCode());
        lowLevelClient.close();
    }
    /**
     * constructHttpHosts函数转换host集群节点IP列表
     */
    public static HttpHost[] constructHttpHosts(List<String> host, int port, String protocol) {
        return host.stream().map(p -> new HttpHost(p, port, protocol)).toArray(HttpHost[]::new);
    }
}
```
该示例代码为判断集群是否存在test索引，当返回"200"（索引存在）或"404"（索引不存在）时，表示正常返回查询结果，集群连接成功。
 #### Elasticsearch RestHighLevelClient连接安全集群（无证书）
使用Elasticsearch 7.10.2 RestHighLevelClient调用"getLowLevelClient()"获取RestLowLevelClient，在不加载安全证书的情况下连接安全模式的OpenSearch集群（支持HTTP协议或HTTPS协议），查询索引"test"是否存在。代码示例如下：
```
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;
import org.apache.http.protocol.HttpContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.Nullable;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
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;
public class RestLowLevelClientExample {
    /**
     * 创建客户端的类，定义create函数用于创建客户端
     */
    public static RestHighLevelClient create(List<String> host, int port, String protocol, int connectTimeout, int connectionRequestTimeout, int socketTimeout,  String username, String password) throws IOException {
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
        SSLContext sc = null;
        try {
            sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new SecureRandom());
        } catch (KeyManagementException | NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        SSLIOSessionStrategy sessionStrategy = new SSLIOSessionStrategy(sc, new NullHostNameVerifier());
        SecuredHttpClientConfigCallback httpClientConfigCallback = new SecuredHttpClientConfigCallback(sessionStrategy,
            credentialsProvider);
        RestClientBuilder builder = RestClient.builder(constructHttpHosts(host, port, protocol))
            .setRequestConfigCallback(requestConfig -> requestConfig.setConnectTimeout(connectTimeout)
                .setConnectionRequestTimeout(connectionRequestTimeout)
                .setSocketTimeout(socketTimeout))
            .setHttpClientConfigCallback(httpClientConfigCallback);
        final RestHighLevelClient client = new RestHighLevelClient(builder);
        logger.info("es rest client build success {} ", client);
        return client;
    }
    /**
     * constructHttpHosts函数转换host集群节点IP列表
     */
    public static HttpHost[] constructHttpHosts(List<String> host, int port, String protocol) {
        return host.stream().map(p -> new HttpHost(p, port, protocol)).toArray(HttpHost[]::new);
    }
    /**
     * trustAllCerts忽略证书配置
     */
    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;
            }
        }
    };
    /**
     * CustomConnectionKeepAliveStrategy函数设置连接的保活时间，主要应对大量短连接的情况和数据请求不高的场景
     */
    public static class CustomConnectionKeepAliveStrategy extends DefaultConnectionKeepAliveStrategy {
        public static final CustomConnectionKeepAliveStrategy INSTANCE = new CustomConnectionKeepAliveStrategy();
        private CustomConnectionKeepAliveStrategy() {
            super();
        }
        /**
         * 最大Keep-Alive的时间（分钟）
         * 这里默认为10分钟，可以根据实际情况设置。可以观察客户端机器状态为TIME_WAIT的TCP连接数，如果太多，可以增大此值
         */
        private final long MAX_KEEP_ALIVE_MINUTES = 10;
        @Override
        public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
            long keepAliveDuration = super.getKeepAliveDuration(response, context);
            // <0 为无限期keep-alive
            // 将无限期替换成一个默认的时间
            if (keepAliveDuration < 0) {
                return TimeUnit.MINUTES.toMillis(MAX_KEEP_ALIVE_MINUTES);
            }
            return keepAliveDuration;
        }
    }
    private static final Logger logger = LogManager.getLogger(RestLowLevelClientExample.class);
    static class SecuredHttpClientConfigCallback implements RestClientBuilder.HttpClientConfigCallback {
        @Nullable
        private final CredentialsProvider credentialsProvider;
        /**
         * The {@link SSLIOSessionStrategy} for all requests to enable SSL / TLS encryption.
         */
        private final SSLIOSessionStrategy sslStrategy;
        /**
         * Create a new {@link SecuredHttpClientConfigCallback}.
         *
         * @param credentialsProvider The credential provider, if a username/password have been supplied
         * @param sslStrategy         The SSL strategy, if SSL / TLS have been supplied
         * @throws NullPointerException if {@code sslStrategy} is {@code null}
         */
        SecuredHttpClientConfigCallback(final SSLIOSessionStrategy sslStrategy,
            @Nullable final CredentialsProvider credentialsProvider) {
            this.sslStrategy = Objects.requireNonNull(sslStrategy);
            this.credentialsProvider = credentialsProvider;
        }
        /**
         * Get the {@link CredentialsProvider} that will be added to the HTTP client.
         *
         * @return Can be {@code null}.
         */
        @Nullable
        CredentialsProvider getCredentialsProvider() {
            return credentialsProvider;
        }
        /**
         * Get the {@link SSLIOSessionStrategy} that will be added to the HTTP client.
         *
         * @return Never {@code null}.
         */
        SSLIOSessionStrategy getSSLStrategy() {
            return sslStrategy;
        }
        /**
         * Sets the {@linkplain HttpAsyncClientBuilder#setDefaultCredentialsProvider(CredentialsProvider) credential provider},
         *
         * @param httpClientBuilder The client to configure.
         * @return Always {@code httpClientBuilder}.
         */
        @Override
        public HttpAsyncClientBuilder customizeHttpClient(final HttpAsyncClientBuilder httpClientBuilder) {
            // enable SSL / TLS
            httpClientBuilder.setSSLStrategy(sslStrategy);
            // enable user authentication
            if (credentialsProvider != null) {
                httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
            }
            return httpClientBuilder;
        }
    }
    public static class NullHostNameVerifier implements HostnameVerifier {
        @Override
        public boolean verify(String arg0, SSLSession arg1) {
            return true;
        }
    }
    /**
     * main函数参考如下，调用create函数创建High Level Client再调用getLowLevelClient()获取Low Level Client，并查询test索引是否存在
     */
    public static void main(String[] args) throws IOException {
        RestHighLevelClient client = create(Arrays.asList("xxx.xxx.xxx.xxx", "xxx.xxx.xxx.xxx"), 9200, "http", 30000, 30000, 30000, "username", "password");
        RestClient lowLevelClient = client.getLowLevelClient();
        Request request = new Request("HEAD", "test");
        Response response = lowLevelClient.performRequest(request);
        System.out.println(response.getStatusLine().getStatusCode());
        lowLevelClient.close();
    }
}
```
表8函数中的变量说明 
| 参数                       | 描述                               |
|:---|:---|
| host                     | 集群访问地址，当存在多个IP地址时，中间用","隔开。      |
| port                     | 集群的连接端口，默认是"9200"。               |
| protocol                 | 连接协议，"http"或者"https"，根据集群实际情况填写。 |
| connectTimeout           | 连接超时时间（毫秒）。                      |
| connectionRequestTimeout | socket连接请求超时时间（毫秒）。              |
| socketTimeout            | socket请求超时时间（毫秒）。                |
| username                 | 访问集群的用户名。                        |
| password                 | 用户名对应的密码。                        |
   
该示例代码为判断集群是否存在test索引，当返回"200"（索引存在）或"404"（索引不存在）时，表示正常返回查询结果，集群连接成功。
 #### Elasticsearch RestHighLevelClient连接安全集群（加载证书）
使用Elasticsearch 7.10.2 RestHighLevelClient调用"getLowLevelClient()"获取RestLowLevelClient，在加载安全证书的情况下连接安全模式+HTTPS协议的OpenSearch集群，查询索引"test"是否存在。代码示例如下：
![](https://support.huaweicloud.com/usermanual-css/public_sys-resources/caution_3.0-zh-cn.png)
连接安全模式+HTTPS协议的OpenSearch集群需要先提前准备好安全证书，操作指导请参见[获取并上传安全证书]。
```
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.Nullable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import javax.net.ssl.SSLContext;import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
public class RestLowLevelClientExample {
    private static final Logger logger = LogManager.getLogger(RestLowLevelClientExample.class);
    /**
     * 创建客户端的类，定义create函数用于创建客户端
     */
    public static RestHighLevelClient create(List<String> host, int port, String protocol, int connectTimeout, int connectionRequestTimeout, int socketTimeout, String username, String password, String certFilePath, String certPassword) throws IOException {
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
        SSLContext sc = null;
        try {
            TrustManager[] tm = {new MyX509TrustManager(certFilePath, certPassword)};
            sc = SSLContext.getInstance("SSL", "SunJSSE");
            //也可以使用SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
            sc.init(null, tm, new SecureRandom());
        } catch (Exception e) {
            e.printStackTrace();
        }
        SSLIOSessionStrategy sessionStrategy = new SSLIOSessionStrategy(sc, new NoopHostnameVerifier());
        SecuredHttpClientConfigCallback httpClientConfigCallback = new SecuredHttpClientConfigCallback(sessionStrategy,
            credentialsProvider);
        RestClientBuilder builder = RestClient.builder(constructHttpHosts(host, port, protocol))
            .setRequestConfigCallback(requestConfig -> requestConfig.setConnectTimeout(connectTimeout)
                .setConnectionRequestTimeout(connectionRequestTimeout)
                .setSocketTimeout(socketTimeout))
            .setHttpClientConfigCallback(httpClientConfigCallback);
        final RestHighLevelClient client = new RestHighLevelClient(builder);
        logger.info("es rest client build success {} ", client);
        ClusterHealthRequest request = new ClusterHealthRequest();
        ClusterHealthResponse response = client.cluster().health(request, RequestOptions.DEFAULT);
        logger.info("es rest client health response {} ", response);
        return client;
    }
    /**
     * constructHttpHosts函数转换host集群节点IP列表
     */
    public static HttpHost[] constructHttpHosts(List<String> host, int port, String protocol) {
        return host.stream().map(p -> new HttpHost(p, port, protocol)).toArray(HttpHost[]::new);}
    static class SecuredHttpClientConfigCallback implements RestClientBuilder.HttpClientConfigCallback {
        @Nullable
        private final CredentialsProvider credentialsProvider;
        private final SSLIOSessionStrategy sslStrategy;
        SecuredHttpClientConfigCallback(final SSLIOSessionStrategy sslStrategy,
            @Nullable final CredentialsProvider credentialsProvider) {
            this.sslStrategy = Objects.requireNonNull(sslStrategy);
            this.credentialsProvider = credentialsProvider;
        }
        @Nullable
        CredentialsProvider getCredentialsProvider() {
            return credentialsProvider;
        }
        SSLIOSessionStrategy getSSLStrategy() {
            return sslStrategy;
        }
        @Override
        public HttpAsyncClientBuilder customizeHttpClient(final HttpAsyncClientBuilder httpClientBuilder) {
            httpClientBuilder.setSSLStrategy(sslStrategy);
            if (credentialsProvider != null) {
                httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
            }
            return httpClientBuilder;
        }}
    public static class MyX509TrustManager implements X509TrustManager {
        X509TrustManager sunJSSEX509TrustManager;
        MyX509TrustManager(String certFilePath, String certPassword) throws Exception {
            File file = new File(certFilePath);
            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, certPassword.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];
        }
    }
    /**
     * main函数参考如下，调用create函数创建High Level Client再调用getLowLevelClient()获取Low Level Client，并查询test索引是否存在
     */
    public static void main(String[] args) throws IOException {
        RestHighLevelClient client = create(Arrays.asList("xxx.xxx.xxx.xxx", "xxx.xxx.xxx.xxx"), 9200, "https", 30000, 30000, 30000, "username", "password", "certFilePath", "certPassword");
        RestClient lowLevelClient = client.getLowLevelClient();
        Request request = new Request("HEAD", "test");
        Response response = lowLevelClient.performRequest(request);
        System.out.println(response.getStatusLine().getStatusCode());
        lowLevelClient.close();
    }
}
```
表9函数中的参数说明 
| 参数                       | 描述                          |
|:---|:---|
| host                     | 集群访问地址，当存在多个IP地址时，中间用","隔开。 |
| port                     | 集群的连接端口，默认是"9200"。          |
| protocol                 | 连接协议，此处填写"https"。           |
| connectTimeout           | 连接超时时间（毫秒）。                 |
| connectionRequestTimeout | socket连接请求超时时间（毫秒）。         |
| socketTimeout            | socket请求超时时间（毫秒）。           |
| username                 | 访问集群的用户名。                   |
| password                 | 用户名对应的密码。                   |
| certFilePath             | 安全证书路径。                     |
| certPassword             | 安全证书密码。                     |
   
该示例代码为判断集群是否存在test索引，当返回"200"（索引存在）或"404"（索引不存在）时，表示正常返回查询结果，集群连接成功。
 #### 获取并上传安全证书
当接入安全模式+HTTPS协议的OpenSearch集群时，必须加载安全证书。可以参考如下步骤获取安全证书，并上传至客户端。
1. 获取安全证书（CloudSearchService.cer）。
   1. 登录[云搜索服务管理控制台](https://console.huaweicloud.com/elasticsearch/)。
   
   2. 在左侧导航栏，选择"集群管理 \> OpenSearch"。
   
   3. 在集群列表，单击目标集群名称，进入集群详情页。
   
   4. 选择"概览"页签，在"网络信息"下方，单击"HTTPS访问"的"下载证书"获取安全证书。
      图1下载安全证书   
      ![](https://support.huaweicloud.com/usermanual-css/images/zh-cn_image_0000002515000613.png) 
    
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*是由用户自定义的证书名称。
   该命令执行后，会提示设置证书密码，并确认密码。请保存该密码，后续接入集群会使用。
   
 
