问题背景

各行各业都在大谈“整合”,每一个“整合”概念背后又是海量数据的支撑。ElasticSearch、Solr等搜索引擎更是在这个风口大显神通。

最近在应用ElasticSearch改造会员系统时遇到了这样一个问题:某一用户在长时间无动作后,再向ES发送请求,先是长时间Loading,而后出现报错“远程主机强迫关闭了一个现有连接”。而在报错后再次发送请求一切又正常了。

从现象上推测,很可能是由于连接超时导致的错误(其实并不完全是)。

大胆猜想,小心求证(此部分并非正解,着急的同学可跳过)

这里梳理下求证过程:

我在springboot项目中采用RestHighLevelClient对ElasticSearch进行操作,直接上代码:

/*** ES开发环境配置类*/
@Configuration
@Conditional(MsgMqDevCondition.class)
public class ElasticSearchDevConfig {@Value("${es.url}")private String esPath;@Value("${es.port}")private String esPort;@Beanpublic RestHighLevelClient restHighLevelClient(){RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost(esPath,Integer.parseInt(esPort),"http")).setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {@Overridepublic RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) {return requestConfigBuilder.setConnectTimeout(90000000)//25hours.setSocketTimeout(90000000);}}));return client;}}

起初我以为只要按论坛上很多文章的说法,将连接时长拉宽就可以解决问题,实则大谬,官方API也只是声称这种配置是为client设置超时时间。

如果仅仅是因为连接超时导致了这个问题,我写个定时任务,高频的维持请求是不是可以解决问题呢?

/*** 定时唤醒ElasticSearch客户端*/
@Component
@Slf4j
public class ElasticClientAwakeTask {@Autowiredprivate RestHighLevelClient restHighLevelClient;@Scheduled(cron = "0 0/2 * * * ?")public void keepESAlive() {try {MainResponse info = restHighLevelClient.info(RequestOptions.DEFAULT);log.info("ES定时唤醒正常,节点名称:"+info.getNodeName());} catch (IOException ignored) {log.error("ES定时唤醒异常:"+ignored.getMessage());}}}

经过验证,问题并没有得到解决。

问题正解

两次鲁莽的尝试并没有解决问题,这个时候就需要坐坐冷板凳了,通过查源码终于发现了问题的关键。

其实每个client都持有一个http连接,并且开启了http的keep-alive策略复用连接。而这个对连接100%信任的复用恰恰引发了问题。

ES highLevelClient 对长连接的实现是把超时时间设置为-1,也就是说客户端永远不超时,服务端设备为了资源的利用率会检测与此设备的连接是否在使用,如果一个连接长时间没有使用,服务端会主动把这个连接回收,而此时客户端并未获得通知,由于ES服务端对客户端连接不负责任的单向清理,导致当有请求触发使用了该连接就会发现与服务端连接不上,产生timeout,客户端此时才会断开此连接。而再次请求时,由于创建了新的连接,客户端与服务端通信又正常了。因此问题的根源在于客户端没有及时发现连接的不可用并断开,需要设置让客户端主动对tcp连接进行探测保活。

通过查阅官方API,我发现其实可以通过HttpClientConfigCallback来控制线程相关的操作。这里需要注意,Java High Level REST Client 是基于  Java Low Level REST client开发的,所以低级API对连接、线程的处理与高级API并不冲突。

解决方案:

/*** ES开发环境配置类*/
@Configuration
@Conditional(MsgMqDevCondition.class)
public class ElasticSearchDevConfig {@Value("${es.url}")private String esPath;@Value("${es.port}")private String esPort;@Beanpublic RestHighLevelClient restHighLevelClient(){RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost(esPath,Integer.parseInt(esPort),"http")).setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {@Overridepublic RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) {return requestConfigBuilder.setConnectTimeout(90000000)//25hours.setSocketTimeout(90000000);}}).setHttpClientConfigCallback((httpAsyncClientBuilder -> {httpAsyncClientBuilder.disableAuthCaching();//禁用身份验证缓存//显式设置keepAliveStrategyhttpAsyncClientBuilder.setKeepAliveStrategy((httpResponse,httpContext) -> TimeUnit.MINUTES.toMillis(3));//显式开启tcp keepalivehttpAsyncClientBuilder.setDefaultIOReactorConfig(IOReactorConfig.custom().setSoKeepAlive(true).build());return httpAsyncClientBuilder;})));return client;}}

关于应用RestHighLevelClient操作ElasticSearch出现“远程主机强迫关闭一个现有连接”的问题探究相关推荐

  1. 远程主机强迫关闭一个现有连接 安卓开发 完美解决版

    远程主机强迫关闭一个现有连接 安卓开发 问题描述 android Studio控制栏报错:远程主机强迫关闭一个现有的连接.构建项目失败.导致项目无法运行. 问题产生原因   在今后的几天中,这个错误经 ...

  2. 远程主机强迫关闭一个现有连接-=-解决办法

    远程主机强迫关闭一个现有连接 在Android studio调试过程中经常会遇到这个问题,解决方法总结如下: 最简单粗暴直接有效 adb kill -server adb start -server ...

  3. SQL SERVER 远程主机强迫关闭一个现有连接

    SQL SERVER 远程主机强迫关闭一个现有连接 在做一个数据比对程序.昨天还能连接的,突然今天就不能连接 首先在数据服务器查看.服务都已启动.客户端能连接.没有其它异常 最后想起,不久之前我把电脑 ...

  4. python post 远程主机强迫关闭了一个现有的连接_ConnectionResetError:[WinError10054远程主机强迫关闭一个现有连接...

    最近在使用Airtest这套框架尝试web自动化界面测试的时候,在脚本之前都可正常运行的情况下,偶有的时候遇到连接错误,报错:Connection abourted. ConnectionResetE ...

  5. Android开发——错误:远程主机强迫关闭一个现有连接——解决办法

    最简单粗暴直接有效 adb kill -server adb start -server 如果不行就只能规规矩矩的查问题了 打开终端窗口 win+R 查看5037端口都有哪些进程 输入 netstat ...

  6. hubbledotnet 远程连接提示:无法从传输连接中读取数据:远程主机强迫关闭一个现有的连接...

    我用本地hubbledotnet(安装32位)去连接服务器hubbledotnet(64位) 提示:无法从传输连接中读取数据:远程主机强迫关闭一个现有的连接 ...

  7. C#远程主机强迫关闭一个现有链接问题简述

    所谓的远程主机强迫关闭一个现有链接,我的理解是:客户端与服务端之中,有一个率先中断了已经建立的SOCKET,从而导致连接的另一端被强行关闭链接------毕竟你连接的另一端已经关闭了,那你还链接个毛啊 ...

  8. Navicat连接SqlServer 提示远程主机关闭一个现有连接

    解决方法:https://docs.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms?view=sql-s ...

  9. 频繁发送socket命令返回:[WinError 10054] 远程主机强迫关闭了一个现有的连接

    第一类 错误原因:发送http请求太过频繁,引起远程主机的怀疑,被网站怀疑是恶意攻击行为. 解决方法: 在发送命令之后关闭连接,防止被认为恶意连接 设置socket默认等待时间 设置读取信息的最大时间 ...

最新文章

  1. ksql中定义的本体在dataModel中不存在
  2. 基于supersocket、C#对JT808协议进行解析构建gps监控平台服务端
  3. VMWare NAT模式和桥接模式的区别
  4. 透过NpetShop 看Web项目开发中的分工合作
  5. Asynchronous(异步处理)
  6. 浅谈 Mybatis中的 ${ } 和 #{ }的区别
  7. Windows编程入门
  8. ccf认证的期刊和会议_ccf推荐AI、CV方向的国际学术期刊、会议
  9. 数字和字符对照关系表常用(编码表)
  10. 软考 系统架构设计师 2009-2018年英语翻译及重点词汇
  11. revit二次开发——过滤器基础
  12. Excel中怎么查找重复值
  13. 判断一个数是不是质数(素数),3种方式介绍
  14. 保险行业数据分析——用户画像 精准营销
  15. 全国哀悼日,网站变成黑白色
  16. linux源码分析之cpu初始化 kernel/head.s,linux源码分析之cpu初始化
  17. 强化IT能力 中国移动OpenStack玩“大”的
  18. JavaEE:网络原理之TCP/IP
  19. 【智能制造】索菲亚家居智能工厂与物流系统建设
  20. 解决连接mysql数据库出现Caused by: com.mysql.cj.exceptions.InvalidConnectionAttributeException: The server tim

热门文章

  1. 序列、列表、列表的方法以及遍历序列
  2. laravel 加谷歌验证
  3. 文件服务器异地容灾,三种异地容灾方案(完整版).pdf
  4. 基于 Python 的时序模型——AMIRA模型
  5. 【H5】用易企秀做H5做完发现页面播放顺序乱套了???请不要单选自动播放
  6. 【读书笔记】吴军阅读与写作讲义
  7. C# Chart之双Y轴图表实现
  8. 微信内打开链接,跳转到公众号关注页面
  9. 用Python写了个工具,完美破解了MySQL!!(建议收藏)
  10. 无影云桌面-网上电脑