irockytan
V2EX  ›  Java

客户端关闭连接导致 ClientAbortException,然后服务端资源无法释放而死掉,该怎么处理比较好?

  •  
  •   irockytan · Dec 23, 2015 via iPhone · 3817 views
    This topic created in 3821 days ago, the information mentioned may be changed or developed.
    Java 提供的 api ,有一个接口处理时间比较长,用户在 app 上往往等不及响应直接返回,导致服务端抛出 ClientAbortException ,此时大量资源无法释放,会出现服务端 OutOfMemory 无法创建新的线程,除了提高这个接口的响应时间让客户减少终断的次数,还有什么办法比较好处理这个问题?
    stack size 已经设置为比较小的值
    10 replies    2015-12-24 19:49:07 +08:00
    Septembers
        1
    Septembers  
       Dec 24, 2015 via Android
    拆分 异步 延迟 队列
    irockytan
        2
    irockytan  
    OP
       Dec 24, 2015 via iPhone
    @Septembers 单个查询请求无法拆分,异步同样无法应用在这里,这个接口需要同步返回,延迟和队列,在客户端调用上,没有效果
    Septembers
        3
    Septembers  
       Dec 24, 2015 via Android
    @irockytan 如果这个查询是可预测的的话可以提前预计算并缓存 来提高响应速度
    SoloCompany
        4
    SoloCompany  
       Dec 24, 2015
    ClientAbortException 只是表象,实质问题仅仅是处理太慢导致请求恶化,根本不是什么资源没释放

    在无法解决瓶颈的前提下,只能是加资源池控制并发量,并且让大量进入的请求在若干秒得不到资源池的时候直接失败
    irockytan
        5
    irockytan  
    OP
       Dec 24, 2015 via iPhone
    @SoloCompany 最后服务器无法响应得到的错误是 java.lang.OutOfMemoryError: unable to create new native thread ,此时 Server 内存尚有剩余, Tomcat 的线程数在 2000 左右, stack size 的值是 1M
    z530151716
        6
    z530151716  
       Dec 24, 2015
    感觉不是客户端强制关闭的原因。
    z530151716
        7
    z530151716  
       Dec 24, 2015
    曾经我有一个服务跟你一样老是报 oom ,也怀疑是 ClientAbortException ,内存飙升, CPU 占用 100%,后来发现是有一段逻辑没处理好,有一句 SQL 在某些情况下会搜索整个表,大约四五 G 。改完就没出现了。
    楼主可以试试把假死时的内存 dump 出来查看
    irockytan
        8
    irockytan  
    OP
       Dec 24, 2015 via iPhone
    @z530151716 问题昨天晚上已经修复了,是一个查询没有用缓存,导致直接去查询一个非常大的视图,所以非常慢,影响了响应,结合访问日志来看,应该是客户端在长时间得不到结果后会有多次刷新,导致连接数增多,而服务端的资源还在处理之前的请求没有结束,导致无法创建更多线程了,可能是我理解有误,这个问题的出现确实和 @SoloCompany 说的那样,是请求处理太慢的而导致资源占用,而不是 ClientAbort 的原因,难怪总有点想不通。
    Lpl
        9
    Lpl  
       Dec 24, 2015 via Android
    @irockytan 哈哈,前些天在测试服务器上测试一个东西的时候也出了类似的情况。你看看是不是数据库爆了,然后导致的数据库与服务器之间连接断开了。

    前些天我遇到的情况是介个样子的,有一个查询 controller 中的某个方法需要的时间是 17s(我用 java 代码测出来的)。然后呢,用户嫌慢,又进行了重复刷新,再加上有很多用户同时访问,又加上测试服务器的数据库比较渣。然后数据库挂了,与服务器之间的通讯也挂掉了,然后整个站就挂了。。。

    不知道我描述清楚了没,解决方法是把以前的那个查询给重写了(写的真渣),并且加了索引,把时间给缩短到了 7s 左右。然后又把数据库连接池的每个连接过期时间设短。就解决了
    irockytan
        10
    irockytan  
    OP
       Dec 24, 2015 via iPhone
    @Lpl 我的情况和你差不多,不过不是数据库挂了,数据库没问题,是 tomcat 没法接受新连接了,解决方案也和你差不多,是数据库的查询引起的,修改 sql 和用缓存久好了
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   5440 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 38ms · UTC 06:45 · PVG 14:45 · LAX 23:45 · JFK 02:45
    ♥ Do have faith in what you're doing.