遇到一个 None of the configured nodes are available 的坑
一、背景:
因现网扫描出来几个漏洞,目前版本使用的springboot2.1.17.RELEASE + elasticsearch6.4.3。
所以需要改造升级:
1、把es升级为elasticsearch6.8.23;
2、给es添加密码;
二、查询资料:
1、ElasticSearch6.8.13解决Log4j CVE-2021-44228漏洞_wwnaitang的博客-优快云博客
2、springboot集成elasticsearch6.81设置密码xpack连接_小栋哟的博客-优快云博客_springboot配置es密码
3、运维(14) docker-compose部署Elasticsearch并设置账号密码_郑清的博客-优快云博客
三、环境:
1、使用docker-compose部署elasticsearch6.8.23
docker-compose.yml文件
version: '3'
services:
elasticsearch:
image: docker.io/elasticsearch:6.8.23
container_name: elasticsearch
restart: always
environment:
- cluster.name=elasticsearch-cluster
- bootstrap.memory_lock=true
- http.cors.enabled=true
- http.cors.allow-origin=*
- discovery.type=single-node
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
volumes:
- /data/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
- /data/elasticsearch/data:/usr/share/elasticsearch/data
- /data/elasticsearch/logs:/user/share/elasticsearch/logs
ports:
- 9200:9200
- 9300:9300
elasticsearch.yml文件(很多报None of the configured nodes are available的坑就在这里,结尾特殊说明)
cluster.name: "elasticsearch-cluster"
network.host: 0.0.0.0
http.port: 9200
http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-headers: Authorization
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
docker-compose启动elasticsearch会报错,因为没加权限,所以加下elasticsearch文件夹的权限
chmod 777 -R elasticsearch/
elasticsearch6.8.23部署成功,开始设置密码
# 进入容器
docker exec -it elasticsearch /bin/bash
# 设置密码-随机生成密码
# elasticsearch-setup-passwords auto
# 设置密码-手动设置密码
elasticsearch-setup-passwords interactive
# 选择Y 一直输入123456(当然自定义了)
# 最后测试访问
curl 127.0.0.1:9200 -u elastic:123456
# 修改elastic密码为123456 (注:执行命令时会让认证之前账号密码)
curl -H "Content-Type:application/json" -XPOST -u elastic 'http://127.0.0.1:9200/_xpack/security/user/elastic/_password' -d '{ "password" : "123456" }'
四、代码
1、Spring Data Elasticsearch有版本要求,参考 Spring Data Elasticsearch - Reference Documentation
因此升级elasticsearch6.8.23时顺带把springboot也升级为了2.2.13.RELEASE
2、升级maven包
<properties>
<java.version>1.8</java.version>
<elasticsearch.version>6.8.23</elasticsearch.version>
<spring-boot.version>2.2.13.RELEASE</spring-boot.version>
</properties>
<dependencyManagement>
<dependencies>
<!--把es版本管理起来,因为springboot2.2.13中使用的es是6.8.13-->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>transport-netty4-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>x-pack-transport</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- es相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<exclusions>
<exclusion>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>transport-netty4-client</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>x-pack-transport</artifactId>
</dependency>
</dependencies>
3、配置
删除原来的elasticsearch配置
spring:
data:
elasticsearch:
cluster-name: elasticsearch-cluster
cluster-nodes: 10.10.10.10:9300,11.11.11.11:9300
repositories:
enabled: true
新增自定义elasticsearch配置
elasticsearch:
cluster-nodes: 10.10.10.10:9300,11.11.11.11:9300
cluster-name: elasticsearch-cluster
cluster-password: elastic:123456
4、ElasticsearchConfig.class代码
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.xpack.client.PreBuiltXPackTransportClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* Created by feng on 2022/9/2.
*/
@Slf4j
@Configuration
@ConfigurationProperties(prefix = "elasticsearch")
@Data
public class ElasticsearchConfig {
private String clusterName;
private String clusterNodes;
private String clusterPassword;
/**
* elasticsearch客户端注入(配置)
*
* @return
* @throws UnknownHostException
*/
@Bean
public TransportClient transportClient() throws UnknownHostException {
TransportClient client = new PreBuiltXPackTransportClient(Settings.builder()
.put("cluster.name", clusterName)
.put("xpack.security.user", clusterPassword)
//增加嗅探机制,找到ES集群,非集群置为false,设置为true时会自动嗅探整个集群的状态,把集群中其他ES节点的ip添加到本地的客户端列表
.put("client.transport.sniff", false)
.build());
//单个IP
//.addTransportAddress(new TransportAddress(InetAddress.getByName("10.10.10.10"), 9300));
//多个IP
String[] hostNamesPort = clusterNodes.split(",");
String host;
int port;
String[] temp;
if (0 != hostNamesPort.length) {
for (String hostPort : hostNamesPort) {
try {
temp = hostPort.split(":");
host = temp[0].trim();
port = Integer.parseInt(temp[1].trim());
client.addTransportAddress(new TransportAddress(InetAddress.getByName(host), port));
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
log.info("初始化ElasticsearchTemplate成功");
return client;
}
}
5、启动运行,报NoNodeAvailableException[None of the configured nodes are available: [{#transport#-1}{Hqhw6raLSIGlpNeHyzxyrA}{xx.xx.xx.xx}{xx.xx.xx.xx:9300}]]
度娘了None of the configured nodes are available的几种可能的原因:
- 查看配置的ip和端口号是否正确,端口号需要配置tcp端口9300
- 查看cluster name是否正确
- 使用的es client版本需要与ES Server版本一致
- 如果集群开启了访问鉴权,将用户名,密码传入
- client.transport.sniff设置成false,ip:port通过addTransportAddress传入
- netty包冲突,直接引入es client用的netty包版本
- springboot和elasticsearch版本不匹配
等等,检查了都没发现问题,后面看了一下elasticsearch的日志,发现报not an SSL/TLS record
[WARN ][o.e.x.s.t.n.SecurityNetty4ServerTransport] [wqbVDEq] exception caught on transport layer [NettyTcpChannel{localAddress=0.0.0.0/0.0.0.0:9300, remoteAddress=/127.0.0.1:37168}],
closing connection
io.netty.handler.codec.DecoderException:
io.netty.handler.ssl.NotSslRecordException:
not an SSL/TLS record: 455300000027000000000000000908004d3603000016696e7465726e616c3a7463702f68616e647368616b6500
Elasticsearch有2种,一种是仅设置密码,没有秘钥证书的,另外一种是设置密码也设置了秘钥证书,我只需要第一种仅设置密码。所以日志可以看出我们把Elasticsearch配置成了需要ssl证书了。
所以改下elasticsearch.yml文件
cluster.name: "elasticsearch-cluster"
network.host: 0.0.0.0
http.port: 9200
http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-headers: Authorization
#开启设置密码
xpack.security.enabled: true
#是否开启ssl证书秘钥
xpack.security.transport.ssl.enabled: false
关闭xpack.security.transport.ssl.enabled: false 后重新部署elasticsearch
启动项目测试成功。
五、后续
but,but,but,后续联调发现这2个参数都要设置ture,不然es就设置不了密码,上面关闭xpack.security.transport.ssl.enabled: false的方式时灵时不灵的。
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
设置为true后,还是没有绕过None of the configured nodes are available问题。有知道的大神可以留言给后面的同行。
-------------------------------------------------------我是虚线--------------------------------------------------------------
最后还是死心了,放弃transport模式,拥抱High-Level Rest吧。
maven如下:
<properties>
<java.version>1.8</java.version>
<elasticsearch.version>6.8.23</elasticsearch.version>
<spring-boot.version>2.2.13.RELEASE</spring-boot.version>
</properties>
<dependencyManagement>
<dependencies>
<!--把es版本管理起来,因为springboot2.2.13中使用的es是6.8.13-->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- es相关 干掉 spring-boot-starter-data-elasticsearch -->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>
</dependencies>
配置如下:(9300改为了9200)
elasticsearch:
cluster-nodes: 10.10.10.10:9200
cluster-user-name: elastic
cluster-password: 123456
cluster-scheme: http
ElasticsearchConfig.class代码
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
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.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Created by feng on 2022/9/2.
*/
@Slf4j
@Configuration
@ConfigurationProperties(prefix = "elasticsearch")
@Data
public class ElasticsearchConfig {
private String clusterNodes;
private String clusterUserName;
private String clusterPassword;
private String clusterScheme;
private HttpHost[] getHttpHosts() {
List<HttpHost> hostList = new ArrayList<>();
String[] addressArray = clusterNodes.split(",");
for (String address : addressArray) {
String host = address.split(":")[0];
Integer port = Integer.parseInt(address.split(":")[1]);
hostList.add(new HttpHost(host, port, clusterScheme));
}
return hostList.toArray(new HttpHost[]{});
}
/**
* 创建带HTTP Basic Auth认证rest客户端
*/
@Bean(name = "client")
public RestHighLevelClient restHighLevelClient() {
RestClientBuilder builder = RestClient.builder(getHttpHosts());
//设置账号密码
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials(clusterUserName, clusterPassword));
builder.setHttpClientConfigCallback(httpClientBuilder -> {
httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
return httpClientBuilder;
});
return new RestHighLevelClient(builder);
}
}
操作es文章就多了,各位请移位:
(三)ES基于Rest Client的JAVA API开发_猿来如此dj的博客-优快云博客_es restclient
中间件:ES组件RestHighLevelClient用法详解 - 腾讯云开发者社区-腾讯云
【ES学习系列】RestHighLevelClient使用实例 - 21karat - 博客园
RestHighLevelClient的基本使用_看见雨声的博客-优快云博客_resthighlevelclient使用
RestHighLevelClient的简单使用_明快de玄米61的博客-优快云博客_resthighlevelclient使用
Java查询Elasticsearch(RestHighLevelClient)_MrWangf的博客-优快云博客_resthighlevelclient查询