ClientAbortException: java.io.IOException: Broken pipe

可能出现原因:

TCP服务端write数据时,收到SIGPIPE信号(连接已经终止)

  1. TCP握手尚未结束时,连接已经close;
  2. 服务端收到一次read,但write了多次;
  3. 连接通道被占满,新连接被拒绝时,client中断了所有连接。

2.分析过程

2.1.初步排查

每次出现该异常时,总是伴随/im/getUsercInfos.json接口的调用。

2.1.1具体现象
  • 异常记录时间=接口请求记录时间(server连接write前记录)-(2至10)ms;
  • 总是ios设备爆出;
  • 总是h端爆出。
2.1.2分析
  1. 可能性一:
    在请求该接口时,ios设备在某种情况下会中断该请求,导致TCP连接中server端无法向client端write数据。即在server端write之前连接已经close,write时出现异常。
    由于只有h端出现,但h、b客户端代码一致,不太可能单独出现,故可能性较低。

  2. 可能性二:
    在第一次连接已经正常握手,并正常close后,server端在此执行write操作。即对一个对端已经关闭的socket调用两次write,报出SIGPIPE信号,导致异常。
    由于只有ios设备有该问题,故可能性较低。

  3. 可能性三:
    请求接口本身问题或并发调用问题,引起了连接close或连接过多超限导致client端close连接。
    目前acceptCount配置100,观察日志,报错时间区间中并没有如此大量的并发请求,且client端收到拒绝信息时,不确定是否会中断所有请求(理论上不会)。故可能性较低。

2.2.细致排查

伴随该异常的接口,入参和出参量较大(猎头端im对话列表1000-3000个是常态),接口处理时间长,且伴随不同程度的连续请求。

2.2.1具体现象
  • 入参传入emNames数量600-4000个,约15000-100000字符长度;
  • 出参返回约60000-500000字符长度;
  • 执行时常约500-4000ms;
2.2.2分析
  1. 可能性一:
    处理报文过长,client端无法解析/处理过大报文,导致本次及下次请求。
    客户端系统对于大报文的处理问题需要测试和调研,故有可能性。

  2. 可能性二:
    处理时间过长,导致当client端并发请求时,当上次请求尚未完成,下次请求会close上次请求,以本次为准。
    调研后发现client端是阻塞请求,但需要进行实际测试,故有可能性。

  3. 可能性三:
    处理时间过长,在握手过程中client自行中断了连接。
    由于执行时间较长,频率较高,客户或设备自己可能触发kill进程或关闭连接等操作,故有可能性。

3.测试过程

3.1.场景设计
  1. 服务端:
    返回参数量大、处理时间长的接口
  2. 客户端:
    h端客户端;大量输入参数;并发调用接口的工具
  3. 接口:
    URL:/im/getTests.json
    入参:emNames (List,每条约24字符)
    出参:PageForm
    逻辑:根据emNames数量,组装并返回同等数量的PageForm(每条约250字符),根据需求sleep若干时间(3000-5000ms)。
3.2.测试报告
3.2.1.IOS
  1. ios,4000参数,3次并发,服务端无sleep: 无问题
    这里写图片描述

  2. ios,4000参数,3次并发,服务端sleep 3000ms: 无问题
    这里写图片描述

  3. ios,2000参数,20次并发,服务端sleep 5000ms,中途client切出: 无问题
    这里写图片描述

  4. ios,2000参数,20次并发,服务端sleep 5000ms,中途client中断: 发现问题,完全符合异常现象
    这里写图片描述
    这里写图片描述

3.2.2.ANDROID
  1. android,2000参数,10次并发,服务端sleep 5000ms,中途client中断: 发现问题,完全符合异常现象
    这里写图片描述
    这里写图片描述
4.1.问题原因

client端用户在杀死进程时,接口的TCP请求尚未完成(未完成的原因是处理时间长)。
导致server端write数据时,收到SIGPIPE信号,抛出Broken pipe异常。
但由于已经杀死了进程,并不会对用户产生任何影响。

4.2.其他结论
  1. ios和android在处理1M以内(尚不清楚有没有最大值)大小报文时,没有问题
  2. ios和android均是阻塞请求,本次请求不会对上次请求造成影响,即使上次请求尚未完成
  3. ios切换至后台,短时间内(5000ms以内,最大值根据系统不同而不同)并不会中断已经存在的TCP连接。
  4. android切换至后台,并不会中断已经存在的TCP连接。
  5. ios、android杀死进程会一并关闭已经存在的TCP连接。
  6. android框架(公司基于google改造的框架)默认并发5线程一组。

5.解决方案

由于kill进程我们无法控制,故只能通过降低接口处理时间,减少用户kill进程时未完成的TCP连接数量。

  1. 会话列表翻页
  2. 会话列表限制展示数量
  3. 客户端分组获取会话列表数据
Broken pipe异常分析报告1.错误描述ClientAbortException: java.io.IOException: Broken pipe可能出现原因:TCP服务端write数据时,收到SIGPIPE信号(连接已经终止)场景:TCP握手尚未结束时,连接已经close;服务端收到一次read,但write了多次;连接通道被占满,新连接被拒绝时,client中断了所有连接。2.分析过程...
这个 异常 是由于以下几个原因造成。 1、 客户端 再发起请求后没有等服务器端相应完,点击了stop按钮,导致服务器端接收到取消请求。 通常情况下是不会有这么无聊的用户,出现这种情况可能是由于用户提交了请求,服务器端相应缓慢,比如业务逻辑有问题等原因,导致页面过了很久也没有刷新出来,用户就有可能取消或重新发起请求。 2、Tomcat服务器在接受用户请求的时候,有其自身的处理能力,线程、服务器等各个资源限制,超出Tomcat承载范围的请求,就会被tomcat停掉,也可能产生该错误。 3、linux的线...
org.apache.catalina.connector.clientAbortException:java.io.IOException: 你的主机中的软件中止了一个已建立的连接
连接太多,到了最大连接数,每个连接处理的速度太慢,而导致处理不过来所以连接断开了 请求报文和返回参数量过大然而导致了client自行中断了连接。 文件过大:处理时间过长,由于执行时间较长或频率较高,程序或服务器出发超时直接结束进程。 数据库配置问题或者是JVM配置太低而导致的,JVM垃圾没有回收,因为有次出现过代码里面死
本文实例讲述了Python提示[Errno 32] Broken pipe 导致线程crash错误 解决 方法。分享给大家供大家参考。具体方法如下: 1. 错误现象 ThreadingHTTPServer 实现的 http 服务,如果 客户端 在服务器返回前, 主动 断开连接,则服务器端会报 [Errno 32] Broken pipe 错,并导致处理线程 crash. 下面先看个例子,python 版本: 2.7 复制代码 代码如下:#!/usr/bin/env python #!coding=utf-8 import os import time import socket import
今天公司技术支持的童鞋报告一个客户的服务不工作了,紧急求助,于是远程登陆上服务器排查问题。 查看采集数据的tomcat日志,习惯性的先翻到日志的最后去查看有没有 异常 的打印,果然发现了好几种 异常 信息,但是最多还是这个: 24-Nov-2016 09:54:21.116 SEVERE [http-nio-8081-Acceptor-0] org.apache.tomcat.uti...