本文介绍如何使用Java、Python、Go语言连接阿里云Elasticsearch集群(ES)。
准备工作
获取集群连接地址
您可以通过VPC私网或公网地址连接到ES集群。
-
VPC私网连接地址:通过VPC私网地址访问ES集群,延迟低,稳定性高。该地址在集群创建成功后默认开启。
-
公网连接地址:通过公网访问ES集群,需手动开启。
如何开启公网访问:
-
登录ES控制台,进入实例基本信息页面。
-
单击左侧导航栏 配置与管理>安全配置,开启公网访问。待集群状态由生效中变更为生效时,表示公网访问已成功开启。
公网访问开启后,公网地址格式为
es-cn-<实例ID>.public.elasticsearch.aliyuncs.com,公网访问白名单默认为空,需手动配置。重要公网地址会降低ES集群的安全性,如果使用公网地址,请务必配置IP白名单,并在使用完毕后及时关闭公网访问。
设置IP白名单
为保障集群安全,您需要将待访问设备的IP地址加入ES集群的VPC私网或者公网白名单,该IP地址所属的设备才能访问ES集群。
-
获取待访问设备IP。
您可以参照以下场景,获取待访问设备的IP地址。
场景
需获取的IP地址
获取方式
在本地设备中连接ES集群
本地设备公网IP。
如果本地设备位于局域网(如家庭或公司网络)内,需将该局域网的公网出口IP地址添加到ES集群的公网白名单中。
通过
curl ipinfo.io/ip查询本地设备公网IP。在不同VPC的ECS实例中连接ES集群
ECS实例的公网IP
登录ECS控制台,在实例列表查看。
在相同VPC的ECS实例中连接ES集群
ECS实例的私网IP
登录ECS控制台,在实例列表查看。
-
将获取到的IP地址添加到白名单分组中。
-
登录ES控制台,进入实例基本信息,单击左侧导航栏 配置与管理>安全配置,单击修改在弹窗中设置VPC私网或者公网访问白名单。
-
单击default分组右侧的配置 ,在弹出的对话框中添加VPC私网或者公网白名单。单个集群最多可配置300个IP或者IP网段,多个IP或者IP网段之间用英文逗号隔开,且逗号前后不能有空格。
-
也可单击新增IP白名单分组,自定义分组名称。
-
白名单分组仅用于IP地址管理,不影响访问权限。所有分组内的IP地址权限相同。
配置类别
格式和示例值
重要注意事项
IPv4地址格式
-
单个IP:
192.168.0.1 -
网段:
192.168.0.0/24
-
禁止访问:
127.0.0.1 -
允许所有访问:
0.0.0.0/0重要存在高危风险,强烈建议不要配置
0.0.0.0/0。部分集群版本(如7.16/8.5)和地域不支持
0.0.0.0/0,请以控制台界面或者报错提示为准。
IPv6地址格式
(仅v2部署架构且所属地域为杭州的集群支持)
-
单个IP:
2401:XXXX:1000:24::5 -
网段:
2401:XXXX:1000::/48
-
禁止所有访问:
::1 -
允许所有访问
::/0重要存在高危风险,强烈建议不要配置
::/0。部分集群版本不支持
::/0,请以控制台界面或者配置提示信息为准。
-
-
配置完成后,单击确认。
-
协议与证书说明
-
为确保兼容性,建议客户端使用的 Java、Python 或 Go 语言版本与ES集群底层运行时的版本保持一致。
-
公网HTTPS:使用权威CA签发的证书,客户端无需特殊配置,直接使用
https://协议连接即可。 -
私网HTTPS:使用自签名证书加密传输,客户端需配置跳过证书校验,详见各语言示例中的私网HTTPS配置。
连接集群
Java
-
安装Java JDK,JDK版本为1.8及以上。
-
配置pom依赖。
重要请将
version设置为正确的ES版本号,只有当version设置正确时才能拉取相关依赖,本示例ES版本为8.17.0。<dependency> <groupId>co.elastic.clients</groupId> <artifactId>elasticsearch-java</artifactId> <version>8.17.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.12.3</version> </dependency> -
配置YML参数,开启自动创建索引:
action.auto_create_index: true。以下示例将连接ES集群并创建名为hr_test的索引。
基础连接示例
以下示例适用于公网HTTPS或私网HTTP场景:
package org.example;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.cat.IndicesResponse;
import co.elastic.clients.elasticsearch.indices.*;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
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.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.*;
import java.io.IOException;
public class RestClientTest {
public static void main(String[] args) {
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("{UserName}", "{YourPassword}"));
// 公网HTTPS使用 "https",私网HTTP使用 "http"
RestClient restClient = RestClient.builder(new HttpHost("{YourEsHost}", 9200, "https"))
.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
}
}).build();
ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
ElasticsearchClient elasticsearchClient = new ElasticsearchClient(transport);
try {
CreateIndexResponse indexRequest = elasticsearchClient.indices().create(createIndexBuilder -> createIndexBuilder
.index("hr_test")
.aliases("foo", aliasBuilder -> aliasBuilder.isWriteIndex(true))
);
System.out.println("Index document successfully! " + indexRequest.acknowledged());
transport.close();
restClient.close();
} catch (IOException ioException) {
// 异常处理
}
}
}
私网HTTPS连接示例
私网HTTPS需额外配置跳过证书校验:
package org.example;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
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.ssl.SSLContexts;
import org.elasticsearch.client.*;
import javax.net.ssl.SSLContext;
public class RestClientTestPrivateHttps {
public static void main(String[] args) throws Exception {
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("{UserName}", "{YourPassword}"));
// 创建信任所有证书的 SSLContext
SSLContext sslContext = SSLContexts.custom()
.loadTrustMaterial(null, (chain, authType) -> true) // 信任所有证书
.build();
RestClient restClient = RestClient.builder(new HttpHost("{YourEsHost}", 9200, "https"))
.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
return httpClientBuilder
.setDefaultCredentialsProvider(credentialsProvider)
.setSSLContext(sslContext) // 设置 SSLContext
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE); // 跳过主机名验证
}
}).build();
ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
ElasticsearchClient elasticsearchClient = new ElasticsearchClient(transport);
// 执行操作...
System.out.println(elasticsearchClient.info());
transport.close();
restClient.close();
}
}
Python
以下代码以ES 8.17.0版本为例,请根据实际ES版本替换版本号。
基础连接示例
以下示例适用于公网HTTPS或私网HTTP场景:
pip install elasticsearch==8.17.0from elasticsearch import Elasticsearch
es = Elasticsearch(
hosts=['https://<YourEsHost>:9200'], # 公网HTTPS使用https://,私网HTTP使用http://
basic_auth=('<UserName>', '<YourPassword>'),
)
print(es.info())
私网HTTPS连接示例
from elasticsearch import Elasticsearch
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) # 关闭SSL警告(可选)
es = Elasticsearch(
hosts=['https://<YourEsHost>:9200'],
basic_auth=('<UserName>', '<YourPassword>'),
verify_certs=False, # 跳过证书校验
ssl_show_warn=False, # 关闭SSL警告
)
print(es.info())
Go
以下以ES 8.x版本为例介绍如何通过Go连接ES,更多Go API Client的使用特性,请参见Elasticsearch Go Client。
基础连接示例
以下示例适用于公网HTTPS或私网HTTP场景:
go get github.com/elastic/go-elasticsearch/v8
package main
import (
"github.com/elastic/go-elasticsearch/v8""log"
)
func main() {
cfg := elasticsearch.Config{
Addresses: []string{"https://<YourEsHost>:9200"}, // 公网HTTPS使用https://,私网HTTP使用http://
Username: "<UserName>",
Password: "<YourPassword>",
}
es, _ := elasticsearch.NewClient(cfg)
res, _ := es.Info()
defer res.Body.Close()
log.Println(res)
}
私网HTTPS连接示例
package main
import (
"crypto/tls""net/http""github.com/elastic/go-elasticsearch/v8""log"
)
func main() {
cfg := elasticsearch.Config{
Addresses: []string{"https://<YourEsHost>:9200"},
Username: "<UserName>",
Password: "<YourPassword>",
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // 跳过证书校验
},
}
es, _ := elasticsearch.NewClient(cfg)
res, _ := es.Info()
defer res.Body.Close()
log.Println(res)
}
参数说明
|
参数 |
说明 |
|
UserName |
默认访问用户名为elastic,该用户具有集群最高权限(可理解为管理员账户)。 出于安全考虑,不建议在生产环境中直接使用此默认管理员账户,您可以通过Elasticsearch X-Pack的RBAC(Role-based Access Control)机制,自定义角色并分配权限,然后将角色分配给用户,实现权限精细化管控,具体操作请参见通过Elasticsearch X-Pack角色管理实现用户权限管控。 |
|
YourPassword |
UserName对应的密码。 |
|
HTTPS |
访问协议,http协议默认开启。 为了保障集群安全性,建议使用HTTPS协议,需手动开启。登录ES控制台进入实例基本信息,单击左侧导航栏 配置与管理>安全配置,开启HTTPS协议。 重要
|
|
YourEsHost |
准备工作中已获取的集群连接地址:
|
|
9200 |
集群的访问端口,VPC私网和公网默认端口号均为9200。 |
FAQ
集群状态健康但客户端无法连接时,按以下方法排查。
路由表诊断
同一VPC下ES连接不通时,检查路由表。Docker安装会修改路由信息,使ES网段路由缺失或指向错误网关。在ECS上执行以下命令查看路由表:
route -n
检查输出中到达ES网段的路由是否存在。如果路由缺失或网关错误,需修复路由配置后重试连接。同时检查企业防火墙是否拦截ES网段流量。
域名与端口校验
使用curl命令验证域名与端口拼接是否正确:
curl -u {UserName}:{YourPassword} https://{YourEsHost}:9200
返回"Could not resolve host"表示域名拼写错误。常见错误包括域名缺少字母、未加端口号。
客户端超时参数配置
Java客户端默认不设置连接超时和Socket超时时间。网络不稳定时连接会长时间阻塞。通过setRequestConfigCallback设置超时参数:
RestClient restClient = RestClient.builder(new HttpHost("{YourEsHost}", 9200, "https"))
.setRequestConfigCallback(builder -> builder
.setConnectTimeout(10000)
.setSocketTimeout(30000))
.setHttpClientConfigCallback(httpClientBuilder ->
httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider))
.build();
ConnectTimeout控制建立连接的超时时间,设为10000毫秒(10秒)。SocketTimeout控制数据读取的超时时间,设为30000毫秒(30秒)。根据网络环境调整这两个值。