前言
前段時間上線了個項目,測試每天早上來摸魚之前會點一點,發(fā)現(xiàn)第一次點會報錯,然后一天都沒問題,剛開始沒在意,后來每天上班來摸魚前點第一次都會出錯,發(fā)現(xiàn)真的摸到魚了,然后就給我提了個bug,說明天早上第一次留給你,你復現(xiàn)一下看看,然后就有了這篇文章了。
問題現(xiàn)象
ES隔一段時間不操作后,再請求es就會報錯Connection reset by peer,之后連續(xù)幾次操作都正常,而且還是必現(xiàn)的,報錯信息如下:
css
復制代碼
org.springframework.dao.DataAccessResourceFailureException: Connection reset by peer; nested exception is java.lang.RuntimeException: Connection reset by peer at org.springframework.data.elasticsearch.core.ElasticsearchExceptionTranslator.translateExceptionIfPossible(ElasticsearchExceptionTranslator.java:76) at org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate.translateException(ElasticsearchRestTemplate.java:378) ...... Caused by: java.io.IOException: Connection reset by peer at org.elasticsearch.client.RestClient.extractAndWrapCause(RestClient.java:828) at org.elasticsearch.client.RestClient.performRequest(RestClient.java:248) at org.elasticsearch.client.RestClient.performRequest(RestClient.java:235) at org.elasticsearch.client.RestHighLevelClient.internalPerformRequest(RestHighLevelClient.java:1514) ...... Caused by: java.io.IOException: Connection reset by peer at sun.nio.ch.FileDispatcherImpl.read0(Native Method) at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39) at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223) ......
問題定位
Caused by: Connection reset by peer
根據(jù)日志可以知道,socket 連接被中斷,連接中斷的原因有很多,比如:
- 服務端或者客戶端異常。
- 客戶端連接超時中斷。
查看日志,這段時間內也沒啥異常信息,服務端也沒異常重啟,也沒出現(xiàn)流量陡量的情況。想到之前在mysql遇到過的問題,mysql的連接如果超過8個小時(默認的時間)不連接,服務端為了節(jié)約資源,會主動把長時間沒連接的客戶端給中斷掉,按照這個思路去排查問題,果然發(fā)現(xiàn)原因如出一轍。導致這個問題的原因有兩個:
- 客戶端采用長連接的方式連接服務端。
- 長時間不連ES,服務端會關閉連接。
1. 客戶端采用長連接的方式連接服務端, 一直持有連接。
ES High Level Rest Client客戶端和服務端的連接采用的是長連接,查閱源碼發(fā)現(xiàn)客戶端創(chuàng)建了client連接池,每個client持有一個http連接,并且開啟http的keep-alive策略復用連接, 策略默認是 -1 ,也就是不過期。
2. 長時間不連ES,服務端會關閉連接。
服務器會有TCP的Keepalive 經(jīng)過一段時間如果沒有操作就會自動斷開連接功能,而ES默認就是取服務器的時長配置linux查看超時時間默認為兩小時:
csharp
復制代碼
# 查看超時時間(單位秒) [root@VM ~]# cat /proc/sys/net/ipv4/tcp_keepalive_time 7200
也就是說如果客戶端超過兩個小時沒有連接服務端,服務端會清除掉連接。
解決方法
修改客戶端的keepalive時間,以單機的ES為例,代碼如下:
ini
復制代碼
@Override public RestHighLevelClient elasticsearchClient() { ? ?List<HttpHost> httpHostsList = new ArrayList<>(); ? ?httpHostsList.add(new HttpHost(uris, Integer.parseInt(port))); ? ?HttpHost[] httpHostsArray = new HttpHost[httpHostsList.size()]; ? ?httpHostsArray = httpHostsList.toArray(httpHostsArray); ? ?RestClientBuilder builder = RestClient.builder(httpHostsArray); ? ?builder.setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder.setKeepAliveStrategy((httpResponse, httpContext) -> 1000 * 60)); ? ?return new RestHighLevelClient(builder); }
application.yaml
yaml
復制代碼
spring: elasticsearch: ? rest: ? ? uris: ip ? ? port: port
以上代碼是基于單機版的es配置的,如果你們的是集群請自行百度設置,重點代碼是設置
setKeepAliveStrategy
這個方法里面。
經(jīng)過這個設置后,線上就沒有出現(xiàn)過類似的問題了。
最后
其實這個問題不僅僅是ES會有的,mysql, CK, 還有其他同類的C/S架構的都會存在這樣的問題,這是一類問題,由于服務端資源優(yōu)化,會回收一些連接,就會導致這個問題,知道這個問題后,我們可以舉一反三,遇到同樣的問題可以快速定位,希望這個問題能對大家有用,最后感謝大家看到這里。。。文章來源:http://www.zghlxwxcb.cn/news/detail-780292.html
作者:TodoCoder
鏈接:https://juejin.cn/post/7113706089350168606
來源:稀土掘金
著作權歸作者所有。商業(yè)轉載請聯(lián)系作者獲得授權,非商業(yè)轉載請注明出處。文章來源地址http://www.zghlxwxcb.cn/news/detail-780292.html
到了這里,關于ES兩個小時沒連接竟然會出現(xiàn)bug,為此老板給我夾了個雞腿。。。的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!