【问题标题】:Unable to connect to Elastic Search intermittently无法间歇性连接到 Elastic Search
【发布时间】:2018-09-25 10:11:52
【问题描述】:

我正在尝试通过 Jest 客户端连接到弹性搜索。

有时,客户端无法连接到弹性搜索集群。

堆栈跟踪:

org.apache.http.NoHttpResponseException: search-xxx-yyy.ap-southeast-1.es.amazonaws.com:443 failed to respond at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:143) at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:57) at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:259) at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:163) at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:273) at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)

弹性搜索集群属于公域,不明白客户端无法连接的原因。

另外,这个问题是间歇性发生的,如果我重试请求,它有时会连接。

感谢任何帮助。谢谢

【问题讨论】:

    标签: elasticsearch elasticsearch-jest


    【解决方案1】:

    当 JestClient 发起 http 请求时,它会在 socket 上调用 read() 并阻塞。当此读取返回 -1 时,这意味着服务器在客户端等待响应之前或期间关闭了连接。

    为什么会发生

    NoHttpResponseException 有两个主要原因:

    。在客户端尝试向下发送请求之前,连接的服务器端已关闭。

    。连接的服务器端在请求中间关闭连接。

    过时的连接(请求前连接已关闭)

    通常这是一个陈旧的连接。使用持久连接时,您可能有一个连接位于连接池中一段时间​​未使用。如果它的空闲时间超过服务器或负载均衡器的 HTTP 保持活动超时,则服务器或负载均衡器将由于其空闲而关闭连接。 Jakarta 客户端的结构不适合接收发生这种情况的通知(它不使用 NIO),因此连接处于半关闭状态。客户端可以检测到此状态的唯一方法是从套接字读取。因此,当您发送请求时,写入成功,因为套接字仅关闭了一半(写入成功,直到您关闭结束),但随后读取表明套接字已关闭。这会导致请求失败。

    连接在请求中关闭

    这可能发生的另一个原因是连接在服务处理时实际上已关闭。您的客户端和服务之间的任何东西都可能关闭连接,包括负载平衡器、代理或服务前面的 HTTP 端点。如果您的活动运行时间很长或者您正在传输大量数据,则出现问题的窗口更大,并且连接更有可能在请求中间丢失。发生这种情况的一个示例是,由于尝试返回大量数据而发生 OutOfMemoryException 后 Java 服务器进程退出。您可以通过查看 TCP 转储来验证这是否是问题所在,以查看在请求运行时连接是否已关闭。此外,这种类型的故障通常在发送请求后一段时间发生,而陈旧的连接故障总是在发出请求时立即发生。

    诊断原因

    NoHttpResponseException 通常是一个陈旧的连接(根据我观察到并帮助人们解决的问题) 当失败总是在提交请求后立即发生时,几乎可以肯定是陈旧的连接问题 如果在等待响应后的一段时间内发生故障,则在发出请求时连接不是陈旧的,并且在请求中间关闭连接 TCPDumps 可能更具决定性。您可以看到连接何时关闭(在请求之前或期间)。

    可以做些什么

    使用更好的客户端

    存在非阻塞 HTTP 客户端,允许调用者知道连接何时关闭,而无需尝试从连接中读取。

    重试失败的请求

    如果您的调用可以安全地重试(例如,它是幂等的),这是一个不错的选择。它还涵盖了除了陈旧的连接故障之外的各种瞬态故障。 NoHttpResponseException 不一定是陈旧的连接,服务可能收到了请求,因此您应该注意仅在安全时重试。

    【讨论】:

    • 感谢您的澄清。你能告诉我如何使用 TCPDump 吗?
    猜你喜欢
    • 2017-10-15
    • 1970-01-01
    • 2018-03-25
    • 1970-01-01
    • 2021-03-20
    • 2021-07-12
    • 1970-01-01
    • 2014-12-20
    • 2019-11-02
    相关资源
    最近更新 更多