JedisConnectionException: java.net.SocketException: Broken pipe (Write failed)

JedisConnectionException: java.net.SocketException: Broken pipe (Write failed)

问题:

查看线上的日志发现线上出现大量的如下的日志, 由于线上只是用redis做缓存。 所以应用没有大量报业务逻辑的错误,

redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketException: Broken pipe (Write failed)
	at redis.clients.jedis.Protocol.sendCommand(Protocol.java:104)
	at redis.clients.jedis.Protocol.sendCommand(Protocol.java:84)
	at redis.clients.jedis.Connection.sendCommand(Connection.java:127)
	at redis.clients.jedis.Connection.sendCommand(Connection.java:121)
	at redis.clients.jedis.BinaryClient.ping(BinaryClient.java:106)
	at redis.clients.jedis.BinaryJedis.ping(BinaryJedis.java:195)
	at com.souche.tracer.org.springframework.boot.actuate.redis.RedisHealthIndicator.doHealthCheck(RedisHealthIndicator.java:71)
	at com.souche.tracer.org.springframework.boot.actuate.health.AbstractHealthIndicator.health(AbstractHealthIndicator.java:66)
	at com.souche.tracer.addon.health.HealthRegistrar.applyAsDouble(HealthRegistrar.java:52)
	at com.souche.tracer.addon.health.HealthRegistrar.access$000(HealthRegistrar.java:21)
	at com.souche.tracer.addon.health.HealthRegistrar$1.call(HealthRegistrar.java:110)
	at com.souche.tracer.addon.health.HealthRegistrar$1.call(HealthRegistrar.java:107)
	at com.souche.tracer.addon.health.Gauge$Child.get(Gauge.java:253)
	at com.souche.tracer.addon.health.Gauge.collect(Gauge.java:345)
	at com.souche.trace.core.jmx.shaded.io.prometheus.client.CollectorRegistry$MetricFamilySamplesEnumeration.findNextElement(CollectorRegistry.java:183)
	at com.souche.trace.core.jmx.shaded.io.prometheus.client.CollectorRegistry$MetricFamilySamplesEnumeration.nextElement(CollectorRegistry.java:216)
	at com.souche.trace.core.jmx.shaded.io.prometheus.client.CollectorRegistry$MetricFamilySamplesEnumeration.nextElement(CollectorRegistry.java:137)
	at com.souche.trace.core.jmx.shaded.io.prometheus.client.exporter.common.TextFormat.write004(TextFormat.java:22)
	at com.souche.trace.core.jmx.shaded.io.prometheus.client.exporter.HTTPServer$HTTPMetricHandler.handle(HTTPServer.java:59)
	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
	at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83)
	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:82)
	at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:675)
	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79)
	at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:647)
	at com.alibaba.ttl.TtlRunnable.run(TtlRunnable.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
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:52)
	at redis.clients.util.RedisOutputStream.write(RedisOutputStream.java:59)
	at redis.clients.jedis.Protocol.sendCommand(Protocol.java:90)
	... 28 common frames omitted

分析

出现这个错误是原因是连接断开了,但是客户端不知道还再往连接里面写入数据导致的。 可能导致这种情况的原因:

  1. 客户端设置不正确,写入大量数据的时候超时. 如果是这个原因可以加上如下配置
#客户端超时时间
redis.timeout=0
#是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
redis.testOnBorrow=true  
#在空闲时检查有效性, 默认false
redis.testWhileIdle=true  
#是否进行有效性检查
redis.testOnReturn=true
  1. redis库的数据量太大, 导致写入数据时候超时。 可以切换下redis的数据库, 使用较空闲的库, 不要都使用默认的0号库

  2. redis有很多的慢查询导致redis阻塞。

如果是慢查询导致的,可以配置redis的SLOWLOG。 让redis 记录下来慢查询命令。 然后就可以查看那些命令超时了。 针对耗时慢的命令进行改造解决。

slowlog 日志的开启可以参考: https://www.cnblogs.com/huanxiyun/p/5580555.html

解决:

  • 我先排查了自己的redis的配置, 发现没有问题。
  • 找运维拿到线上redis的同一个库的慢查询语句,发现耗时都挺快的, 没有特别慢的
  • 由于我们很多个应用都使用同一个redis库, 怀疑可能是库数据量太大,运维让我切换其他redis库。 切换后问题解决

你可能感兴趣的:(JedisConnectionException: java.net.SocketException: Broken pipe (Write failed))