ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

JedisConnectionException: java.net.SocketException: Broken pipe (Write failed) 问题排查

2022-08-19 21:03:27  阅读:225  来源: 互联网

标签:SocketException java redis failed jedis 连接 客户端


问题描述

笔者有2个应用会不定时请求redis,其中一个应用大约每分钟请求一次,可以正常请求,但是另一个大约每小时请求一次的应用,经常出现Broken pipe (Write failed)报错,具体报错信息如下:

redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketException: Broken pipe (Write failed)
	at redis.clients.jedis.Connection.flush(Connection.java:282)
	at redis.clients.jedis.Connection.getBinaryMultiBulkReply(Connection.java:222)
	at redis.clients.jedis.Jedis.hgetAll(Jedis.java:780)
	...
Caused by: java.net.SocketException: Broken pipe (Write failed)
	at java.net.SocketOutputStream.socketWrite0(Native Method)
	at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
	at java.net.SocketOutputStream.write(SocketOutputStream.java:155)
	at redis.clients.util.RedisOutputStream.flushBuffer(RedisOutputStream.java:31)
	at redis.clients.util.RedisOutputStream.flush(RedisOutputStream.java:213)
	at redis.clients.jedis.Connection.flush(Connection.java:279)
	... 26 more	

问题定位

定位到redis服务端配置了3600秒的超时时间,即如果客户端连接超过3600秒空闲,那么就会被redis服务端主动清理掉。笔者大约每小时请求一次redis的应用,若请求时间间隔超过1小时,会被redis服务端认为连接是空闲的,然后把连接清理掉,此时客户端在去请求redis,就会出现报错: Broken pipe (Write failed)

解决方案

笔者首先尝试调大客户端socketTimout的超时时间,让客户端socketTimout的时间超过3600秒,如:7200秒。调整后发现,大约每小时请求一次redis的应用,仍然会出现 Broken pipe (Write failed)报错。由此可见,当客户端和服务端都包含超时的配置时,redis会以服务端为准。

既然调整客户端的超时配置没有效果,服务端仍然会清理空闲的连接。那么客户端是否可以把服务端清理的连接,主动关闭掉呢?然后在需要时在重建连接。按照这个思路,笔者在每次请求redis前,会先执行ping操作。若ping成功了,说明socket连接还没被清理,可以直接请求redis;若ping 不成功,那么会抛出异常,捕获异常后在关闭客户端连接,后面在执行请求redis的命令时,会重新建立socket连接。以下是捕获异常后关闭连接的相关代码。

    try {
      String result = jedis.ping();
      LOGGER.debug("ping redis: {}", result);
    } catch (Exception e){
      LOGGER.warn("ping failed, close jedis and reconnect, {}", e.getMessage());

      try {
        jedis.close();
        LOGGER.info("jedis closed");
      } catch (Exception e1){
        LOGGER.warn("close jedis failed, {}", e1.getMessage());
      }
    }

通过上述方案,客户端空闲超过1小时后,向redis请求会抛出异常 Broken pipe (Write failed),程序捕获异常后关闭客户端连接,然后客户端重建连接,在执行请求就恢复正常了。

参考资料

  1. Redis客户端连接的空闲连接超时时间(timeout)的设置

标签:SocketException,java,redis,failed,jedis,连接,客户端
来源: https://www.cnblogs.com/ljhbjehp/p/16603248.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有