我正在尝试通过Jest Client连接到弹性搜索。
有时,客户端无法连接到弹性搜索群集。
堆栈追踪:
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)
弹性搜索群集属于公共域,因此我不明白为什么客户端无法连接。
此外,问题间歇性地发生,如果我重试请求,它有时会连接。
感谢任何帮助。感谢
答案 0 :(得分:1)
当JestClient发起http请求时,它将在套接字上调用read()并阻止。当此读取返回-1时,这意味着服务器在客户端等待响应之前或期间关闭了连接。
为什么会发生
NoHttpResponseException的主要原因有两个:
。在客户端尝试向下发送请求之前,连接的服务器端已关闭。
。连接的服务器端在请求过程中关闭连接。
失效连接(连接在请求前关闭)
通常这是一个过时的连接。使用持久性连接时,您可能有个连接闲置在连接池中。如果空闲时间超过服务器或负载平衡器的HTTP保持活动超时时间,则服务器或负载平衡器将由于其空闲而关闭连接。 Jakarta客户端的结构未接收到有关此事件的通知(它不使用NIO),因此连接处于半关闭状态。客户端可以检测到此状态的唯一方法是从套接字读取。因此,当您发送请求时,写入成功,因为套接字仅被关闭一半(写入成功直到您关闭末端),但是随后的读取表明套接字已关闭。这会导致请求失败。
连接在请求中关闭
可能发生此事件的另一个原因是,连接在服务正在使用时实际上已关闭。客户端和服务之间的任何内容都可能会关闭连接,包括负载平衡器,代理或服务前面的HTTP端点。如果您的活动运行时间很长,或者您正在传输大量数据,则出现问题的窗口会更大,并且在请求中间可能会丢失连接。发生这种情况的一个示例是,由于尝试返回大量数据而导致OutOfMemoryException发生后,Java服务器进程退出。您可以通过查看TCP转储以查看在请求进行过程中连接是否关闭,来验证这是否是问题。同样,这种类型的故障通常在发送请求后的一段时间内发生,而陈旧的连接故障总是在发出请求后立即发生。
诊断原因
NoHttpResponseException通常是一个过时的连接(根据我观察到并帮助人们的问题) 当提交请求后总是立即发生故障时,几乎可以肯定的是陈旧的连接是问题所在 如果在等待响应后出现故障的时间很短,那么发出请求时连接就不会失效,并且在请求中间关闭连接 TCPDumps可以更具决定性。您可以看到何时关闭连接(在请求之前或期间)。
可以做什么
使用更好的客户
存在不阻塞的HTTP客户端,它使调用者可以知道何时关闭连接,而不必尝试从连接中读取。
重试失败的请求
如果您的呼叫可以重试(例如,幂等),那么这是一个不错的选择。除过时的连接故障外,它还涵盖了各种瞬态故障。 NoHttpResponseException不一定是陈旧的连接,并且服务可能已收到请求,因此您应注意仅在安全的情况下重试。