本文介绍如何使用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秒)。根据网络环境调整这两个值。
如何测试ECS连接Elasticsearch实例的网络延迟及公网访问说明
外部ECS可以通过ES实例的公网连接地址访问阿里云Elasticsearch,公网访问是受支持的连接方式,使用前需确认实例已开启公网访问,且该ECS的公网IP已加入公网访问白名单(集群连接地址的获取与IP白名单配置见本文「准备工作」)。公网链路经过的网络跳数更多、路径更长,相比同一VPC内的私网连接存在明显更高的网络延迟,也更容易受链路抖动影响,因此生产环境优先使用VPC私网连接地址,公网连接仅用于测试、临时排查或确实无法打通私网的场景。在ECS上可以通过以下两种方法测量到ES实例的网络延迟:
-
ping:验证基础连通性并观察往返时延(RTT)。在ECS上执行以下命令,将
{YourEsHost}替换为ES实例的连接地址:ping {YourEsHost}重点关注平均RTT与丢包率:RTT明显偏高或存在丢包,说明ECS到ES之间的链路质量较差。部分网络环境或安全策略会禁用ICMP,此时ping不通并不代表ES服务不可用,应改用「域名与端口校验」中的curl命令确认端口连通性。
-
MTR:逐跳追踪链路,定位网络瓶颈。MTR是通用的链路诊断工具,阿里云ECS镜像不保证预装,需先在ECS上自行安装,安装完成后执行以下命令:
mtr -r -c 100 {YourEsHost}逐跳查看每一跳的丢包率与延迟:若从某一跳开始丢包率或延迟持续升高,则瓶颈位于该跳及其之后的链路,据此可以判断问题出在ECS出口、中间公网链路还是ES接入侧。
如果测得的延迟偏高且业务对时延敏感,改用同地域、同一VPC的私网连接地址;如需进一步收敛网络不稳定带来的请求阻塞,可参考「客户端超时参数配置」调整客户端的连接超时与读取超时。
频繁出现No alive nodes found报错且升级配置无效的排查方法
客户端反复抛出No alive nodes found报错时,通常并非集群资源不足,而是客户端在其维护的节点列表中找不到任何可用节点,多由客户端到集群之间的网络连接不稳定、请求超时或路由异常导致,因此仅升级集群配置往往无法解决问题,应优先从网络连接层面排查。按以下三步定位:
-
确认客户端到ES的网络拓扑路径。先明确客户端使用的是VPC私网连接地址还是公网连接地址,再检查是否存在跨地域访问、跨VPC访问或公网长链路等场景,这些场景更容易出现链路抖动,导致节点探测失败。若当前走公网或跨地域连接,可参考本文「如何测试ECS连接Elasticsearch实例的网络延迟及公网访问说明」测量链路质量,条件允许时优先改用同地域、同一VPC的私网连接地址。
-
检查客户端日志上下文。不要只看
No alive nodes found这一行,向上查看与之伴随出现的具体错误,确认是否存在连接超时(connect timeout)、读取超时(socket timeout)、SSL/TLS握手失败或证书校验失败等信息。伴随错误决定后续动作方向:如果是超时类错误,进入第3步的超时参数调整;如果是SSL/TLS或证书类错误,参考本文「协议与证书说明」以及各语言连接示例中的私网HTTPS配置,修正协议与证书配置。 -
结合本文已有章节做综合排查。参考「路由表诊断」检查ECS到ES网段的路由是否缺失或网关错误(例如Docker安装修改了路由),以及企业防火墙是否拦截ES网段流量;参考「客户端超时参数配置」为客户端显式设置连接超时与Socket超时,避免网络不稳定时请求长时间阻塞并被判定为节点不可用。
若以上网络层面的排查均无异常,再结合集群监控确认是否确实存在资源瓶颈,避免直接以升级配置作为首选手段。