V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
irockytan
V2EX  ›  Java

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

  •  
  •   irockytan · 2015-12-23 23:44:34 +08:00 via iPhone · 3292 次点击
    这是一个创建于 3276 天前的主题,其中的信息可能已经有所发展或是发生改变。
    Java 提供的 api ,有一个接口处理时间比较长,用户在 app 上往往等不及响应直接返回,导致服务端抛出 ClientAbortException ,此时大量资源无法释放,会出现服务端 OutOfMemory 无法创建新的线程,除了提高这个接口的响应时间让客户减少终断的次数,还有什么办法比较好处理这个问题?
    stack size 已经设置为比较小的值
    10 条回复    2015-12-24 19:49:07 +08:00
    Septembers
        1
    Septembers  
       2015-12-24 00:12:13 +08:00 via Android
    拆分 异步 延迟 队列
    irockytan
        2
    irockytan  
    OP
       2015-12-24 00:30:07 +08:00 via iPhone
    @Septembers 单个查询请求无法拆分,异步同样无法应用在这里,这个接口需要同步返回,延迟和队列,在客户端调用上,没有效果
    Septembers
        3
    Septembers  
       2015-12-24 00:34:52 +08:00 via Android
    @irockytan 如果这个查询是可预测的的话可以提前预计算并缓存 来提高响应速度
    SoloCompany
        4
    SoloCompany  
       2015-12-24 01:53:50 +08:00
    ClientAbortException 只是表象,实质问题仅仅是处理太慢导致请求恶化,根本不是什么资源没释放

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

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

    不知道我描述清楚了没,解决方法是把以前的那个查询给重写了(写的真渣),并且加了索引,把时间给缩短到了 7s 左右。然后又把数据库连接池的每个连接过期时间设短。就解决了
    irockytan
        10
    irockytan  
    OP
       2015-12-24 19:49:07 +08:00 via iPhone
    @Lpl 我的情况和你差不多,不过不是数据库挂了,数据库没问题,是 tomcat 没法接受新连接了,解决方案也和你差不多,是数据库的查询引起的,修改 sql 和用缓存久好了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2446 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 15:23 · PVG 23:23 · LAX 07:23 · JFK 10:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.