早上的阳光 2017-04-21 02:09 采纳率: 0%
浏览 3280

Elasticsearch java Client 分页时连接关闭问题

最近在做一个es 深度钻取功能,对源数据查询es默认分页时10条,于是做了一个分页界面,Client 写成单例模式了,每次返回时关闭client.close() 就会出现bug:
NodeAvailableException[None of the configured nodes are available: [{#transport#-1}{192.168.170.69}{192.168.170.69:9300}]]
at org.elasticsearch.client.transport.TransportClientNodesService.ensureNodesAreAvailable(TransportClientNodesService.java:290)
at org.elasticsearch.client.transport.TransportClientNodesService.execute(TransportClientNodesService.java:207)
at org.elasticsearch.client.transport.support.TransportProxyClient.execute(TransportProxyClient.java:55)
at org.elasticsearch.client.transport.TransportClient.doExecute(TransportClient.java:288)
at org.elasticsearch.client.support.AbstractClient.execute(AbstractClient.java:359)
at org.elasticsearch.action.ActionRequestBuilder.execute(ActionRequestBuilder.java:86)
at org.elasticsearch.action.ActionRequestBuilder.execute(ActionRequestBuilder.java:56)


不关闭虽然用了同一个实例,避免了每次请求,新生成新的实例,但是考虑连接总要关闭的,不知道有没有好的解释和办法?

  • 写回答

1条回答 默认 最新

  • 你知我知皆知 2024-08-05 18:54
    关注

    以下回答参考 皆我百晓生券券喵儿 等免费微信小程序相关内容作答,并由本人整理回复。

    这个问题是由于 Elasticsearch 服务端没有正确处理连接池的关闭。当客户端尝试获取连接时,如果没有找到可用的连接,就会抛出 NodeUnavailableException。如果你的客户端试图在没有可用连接的情况下进行操作,那么就会出现你遇到的问题。

    为了解决这个问题,你可以采取以下措施:

    1. 在客户端中添加一个 try-catch 块来捕获 NodeUnavailableException 并处理它。
    public class ElasticsearchClient {
        private static final TransportClient transportClient = new TransportClient(new JsonTransportClientConfiguration());
        private static volatile ElasticsearchClient instance;
    
        public static synchronized ElasticsearchClient getInstance() {
            if (instance == null) {
                instance = new ElasticsearchClient();
            }
            return instance;
        }
    
        public void close() {
            try {
                transportClient.close();
            } catch (IOException e) {
                // Handle exception here.
            }
        }
    
        public TransportClient getTransportClient() {
            return transportClient;
        }
    }
    
    1. 如果你需要保持同一客户端的实例,但仍然需要在每次调用 getTransportClient() 方法时自动关闭连接,可以使用线程安全的锁来实现这一点:
    public class ElasticsearchClient {
        private static final Object lock = new Object();
    
        private static final TransportClient transportClient = new TransportClient(new JsonTransportClientConfiguration());
    
        public static synchronized ElasticsearchClient getInstance() {
            if (transportClient.isClosed()) {
                synchronized (lock) {
                    if (!transportClient.isClosed()) {
                        transportClient = new TransportClient(new JsonTransportClientConfiguration());
                    }
                }
            }
            return getInstance();
        }
    
        public void close() {
            try {
                transportClient.close();
            } catch (IOException e) {
                // Handle exception here.
            }
        }
    
        public TransportClient getTransportClient() {
            return transportClient;
        }
    }
    

    这样,即使有多个线程同时访问 getInstance() 方法,也不会造成问题。

    评论

报告相同问题?