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