常见现象的故障分析

时间:2022-08-18 23:42:39
现象倒推一:Java Web应用的连接数暴增
最大的可能是,Web应用的线程调用路径中阻塞在某个远端资源上。
  • 线程向某个远端资源发起的请求被阻塞,可能是以下原因:
    • 连接受阻,如等待client端连接池的空闲连接,如远端服务连接数满;
    • 响应迟迟没有返回,如数据库中的记录被“表锁”或“行锁”,如数据库有大量慢查询;
 
常见的连接超时时间
为了让 大家一看到线上日志某些刚刚好的时间就能反应过来,总结如下:
  • memcache
    • PHP下,Memcache::connect 函数传入的 timeout 参数代表连接超时时间,单位秒。默认值1秒
      • 注:修改此值之前请三思,过长的连接超时时间可能会导致失去所有的缓存优势。 
    • Java下,
      • spymemcached 里,配置 opTimeout 代表操作超时时间,默认值2.5秒
      • xmemcahced 里,opTimeout 的定义与spy 一样,默认值1秒
  • mysql
    • wait_timeout:服务器关闭非交互连接之前等待活动的秒数,默认值28800秒(即8小时);
    • connect_timeout:在获取链接时,等待握手的超时时间,只在登录时有效,默认值10秒
    • innodb_lock_wait_timeout:一个 InnoDB 事务遇到一个行锁,等待的超时时间,默认值50秒,届时会打印“Lock wait timeout exceeded; try restarting transaction”错误;
  • mongodb
    • Java下,
      • MongoOptions.maxWaitTime:连接上阻塞线程的最大等待时间,默认值120秒
      • MongoOptions.connectTimeout:建立新连接超时时间, (注意Only used for new connections) 默认无限制
      • MongoOptions.socketTimeout:socket通讯超时时间,默认无限制
现象倒推二:Java应用频繁 fullgc
频繁 fullgc 大致有几种原因:
第一种,还是由于某一个资源成为瓶颈,导致大量线程进入 blocked 状态,新的 Requests 源源不断进入,不断开启新线程。加之线程在内存中做了很多运算,且这些内存无法收回,导致 old generation(旧生代内存区)占用比例超过阈值(此阈值由 JVM 参数 CMSInitiatingOccupancyFraction设定,默认值是90%),进一步导致新对象分配没有更多的空间,从而频繁触发 fullgc。
举例,由于某段代码没有释放数据库连接——>连接池中的连接耗尽——>部分线程无限 TIMED_WAITING ——>其余线程都 Blocked——>开启新线程——>频繁引发GC——>占用大量CPU——>应用挂起。
 
第二种,产生了大量大内存对象,占用了大量堆空间,引发 fullgc 。
可以将当时的 memory dump 文件经由 MAT 工具分析,找到对应的对象或直接找到类。