Spring Web容器响应异常排查_Poller线程异常退出

news2024/9/22 19:20:40

问题一_系统响应异常

问题现象

04-11 18点左右客户反馈系统很慢;18点多,反馈pda登录异常;

19:20左右,本地网页登录,某些请求超时;某些正常; 短时间定位后无头绪,保留了stack和dump信息后重启服务,系统恢复正常;
在这里插入图片描述

排查思路

  • 基于请求链路,排除了nginx的原因;是后端服务的问题;当时出现问题的时候,直接对后端接口进行请求,多数也卡住了。事后查看后台的日志,部分请求有打印,部分无;说明请求尚未到达业务层;于是怀疑http接入有问题;

  • 基于nio处理流程,重点分析涉及请求缓存的地方,他们是可能的阻塞点,有两个地方

    • Poller类里面的events队列
    • 业务线程池的queue
      在这里插入图片描述
      在这里插入图片描述

分析过程

stack trace分析

  • 业务线程很多是waiting状态,故非业务线程忙碌;而Acceptor和Poller的线程状态也正常;
"http-nio-9999-exec-743" #181220 daemon prio=5 os_prio=0 tid=0x00007f785c00f000 nid=0x5758 waiting on condition [0x00007f763e6f0000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00000005c6786808> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
    at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
    at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:103)
    at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:31)
    at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)

"http-nio-9999-Acceptor-0" #216 daemon prio=5 os_prio=0 tid=0x00007f78aee2b000 nid=0xfc runnable [0x00007f76699ab000]
   java.lang.Thread.State: RUNNABLE
    at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
    at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:422)
    at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:250)
    - locked <0x00000005c67867c0> (a java.lang.Object)
    at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:448)
    at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:70)
    at org.apache.tomcat.util.net.Acceptor.run(Acceptor.java:95)
    at java.lang.Thread.run(Thread.java:748)

"http-nio-9999-ClientPoller-0" #214 daemon prio=5 os_prio=0 tid=0x00007f78af23e000 nid=0xfa runnable [0x00007f7669bad000]
   java.lang.Thread.State: RUNNABLE
    at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
    at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
    at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
    at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
    - locked <0x00000005c690fc48> (a sun.nio.ch.Util$3)
    - locked <0x00000005c690fc38> (a java.util.Collections$UnmodifiableSet)
    - locked <0x00000005c690fc58> (a sun.nio.ch.EPollSelectorImpl)
    at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
    at org.apache.tomcat.util.net.NioEndpoint$Poller.run(NioEndpoint.java:744)
    at java.lang.Thread.run(Thread.java:748)

dump文件分析

  • PollerEvent有2k+实例,比较可疑
    在这里插入图片描述

  • NioEndpoint里面的poller对象分析

    • 为什么是一个数组,有两个实例
    • events分布极不均匀,pollers[0]里面的events数量只有58个;pollers[1]里面的events数量有2014个;
      在这里插入图片描述

源码分析

  • 查看现象的版本为tomcat-embed-core-9.0.13.jar,切到对应版本的源码,发现构造了Poller数组,启动了多个线程;
    在这里插入图片描述

  • 查看当时的stack trace,只有一个Poller线程;
    在这里插入图片描述

  • 查看线上运行正常应用的stack trace,有两个Poller线程
    在这里插入图片描述

问题原因

有一个Poller线程挂掉了,导致有些请求一直没有处理;表现为有的请求正常,有的不正常;
为什么挂掉了,见下面的继续分析


问题二_Poller线程挂掉

问题现象

见上一个问题的原因。jstack trace里面,有一个Poller线程挂掉了

可疑信息

  • 查看当天的日志,看到一个内存溢出;这个是可疑点;从这次内存溢出到上一个问题出现,中间未重启服务
    在这里插入图片描述

分析

  • 内存溢出打印的是业务线程,且后面通过jstack查看线程快照,该线程是正常的;可能原因:
    • 线程异常处理机制,往上抛出影响到入口线程(Poller)
    • 内存不够,其他线程业务执行被影响导致异常结束了
  • 本地demo复现内存溢出场景,限制jvm内存 (基于tomcat-embed-core:9.0.73版本压测)
    • 场景1:单个请求;内存溢出,报错,但线程运行正常;下一个请求正常受理;
      • 见后面的线程异常处理机制简介,线程未捕获异常,向上抛出,和其他线程隔离,不影响;异常处理后不影响线程的下一次调度
    • 场景2:压测;大量内存溢出错误,线程异常(本次Acceptor和Poller线程均异常退出),无法接受新的请求;查看线程快照,无Acceptor和Poller线程线程
      在这里插入图片描述
      在这里插入图片描述

原因

内存溢出,导致Poller线程异常退出;

相关知识点

spring http请求处理大概过程

tomcat-embed-core-9.0.13.jar

  • acceptor处理

    • thread name:http-nio-8080-Acceptor (8080是端口号)
    • 职能:接收新的tcp请求,并将socket连接注册到poller
    • 代码流程(Acceptor#run)
      • 获取socket连接。NioEndPoint.serverSocketAccept()
        • 从serverSock.accept取socket连接
      • 向poller注册socket连接,NioEndpoint.setSocketOptions
        • poller.register
          • 将事件添加到队列(Poller#events)
  • poller处理

    • thread name:http-nio-8080-Poller
    • 职能:poller接收acceptor注册的socket连接,对其注册监听事件,读取到信息后,提交给容器的线程池处理
    • 代码流程(Poller#run)
      • 调用events()方法,对队列中所有原始socket去注册事件
      • 调用selector.selectNow()和selector.select()方法监听是否有事件发生(上一步注册的事件)
      • 如果selector检测到有事件发生,调用poller#processKey处理
        • processSocket
          • sc = processorCache.pop();
          • if sc == null , sc = new …;
          • 提交到容器的IO线程池处理(executor.execute(sc))
      • 调用timeout方法,做超时处理如果有
  • http 线程池处理

    • thread name: http-nio-8080-x
    • 职能:实际的业务处理,最终会提交到Http11Processor#service,然后分发给Controller层处理

线程异常处理机制简介

说明

Thread出现未捕获的异常时,JVM会调用线程对象的dispatchUncaughtException方法;
未指定exceptionHandler的情况下,会通过threadGroup来处理(直至system group),最终通过控制台输出;

相关代码

Thread#dispatchUncaughtException

线程异常时,会

/**
 * Dispatch an uncaught exception to the handler. This method is
 * intended to be called only by the JVM.
 */
private void dispatchUncaughtException(Throwable e) {
    getUncaughtExceptionHandler().uncaughtException(this, e);
}

/**
 * Returns the handler invoked when this thread abruptly terminates
 * due to an uncaught exception. If this thread has not had an
 * uncaught exception handler explicitly set then this thread's
 * <tt>ThreadGroup</tt> object is returned, unless this thread
 * has terminated, in which case <tt>null</tt> is returned.
 * @since 1.5
 * @return the uncaught exception handler for this thread
 */
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
    return uncaughtExceptionHandler != null ? uncaughtExceptionHandler : group;
}

ThreadGroup#uncaughtException

public void uncaughtException(Thread t, Throwable e) {
if (parent != null) {
parent.uncaughtException(t, e);
} else {
Thread.UncaughtExceptionHandler ueh =
Thread.getDefaultUncaughtExceptionHandler();
if (ueh != null) {
ueh.uncaughtException(t, e);
} else if (!(e instanceof ThreadDeath)) {
System.err.print("Exception in thread “”
+ t.getName() + “” ");
e.printStackTrace(System.err);
}
}
}

在这里插入图片描述
在这里插入图片描述

参考资料

  • tomcat nio:https://cloud.tencent.com/developer/inventory/1620

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/440139.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

球友的一个帖子,半夜三点给我整睡不着了……

文章目录 一、起因二、建议1、括号和缩进2、仔细审题3、独立思考4、早起的好办法5、chatgpt会代替人类吗&#xff1f; 三、解决1、数据结构2、初始化3、判定 一、起因 事情的起因源自于星球里面一位球友的帖子&#xff0c;本来三点醒来上完厕所打算继续睡&#xff0c;突然手机响…

无人机应急救援有保障吗?如何实现救援?

无人机应急救援有保障吗?如何实现救援?中国自然灾害种类较多&#xff0c;分布地域广&#xff0c;发生频率较高。当遭遇洪水、火灾、洪水、地震、暴雪等灾害事故时&#xff0c;常规的信息通信基础设施受到损伤&#xff0c;导致信号中断。如果灾害事故地点相对偏僻&#xff0c;…

淄博旅游“一夜爆火”,五一流量大盘已经开启

全民调休换来的五一小长假即将来临&#xff0c;经过几年“禁锢”后&#xff0c;这两年的旅游业开始回暖。 而今年国内旅游黑马竟指向了新人淄博。 山东淄博烧烤一直以来都“小有名气”&#xff0c;但是这只在周边城市&#xff0c;或者部分人群里传播&#xff0c;而在今年&…

来使用分支语句和循环语句实现一个小游戏吧(猜数字游戏)

猜数字游戏 1.代码展示2.菜单设计3.主函数部分3.随机数设计 1.代码展示 #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <stdlib.h> #include <time.h>void menu() {printf("************************\n");printf("*** 1.p…

移动端导航设计

根据产品层级的深度和广度&#xff0c;选择适合的导航模式&#xff0c;是产品设计中的关键一环。 任何APP的组织信息都需要以某种导航框架固定起来&#xff0c;一个新的产品合适的导航框架&#xff0c;决定了产品之后的延伸和扩展。 移动端的屏幕尺寸就这么大&#xff0c;操作方…

java定位系统源码,通过独特的射频处理,配合先进的位置算法,可以有效计算出复杂环境下的人员与物品的活动信息

智慧工厂人员定位系统源码&#xff0c;区域电子围栏管控源码 文末获取联系&#xff01; 在工厂日常生产活动中&#xff0c;企业很难精准地掌握访客和承包商等各类人员的实际位置&#xff0c;且无法实时监控巡检人员的巡检路线&#xff0c;当厂区发生灾情或其他异常状况时&#…

Layer组件多个iframe弹出层打开与关闭及参数传递

Layer官网地址&#xff1a;http://layer.layui.com/ 1、多个iframe弹出层&#xff08;非嵌套&#xff09; 1.打开iframe弹出层js代码 &#xff08;1&#xff09;示例一&#xff1a; content参数可传入要打开的页面&#xff0c;type参数传2&#xff0c;即可打开iframe类型的弹层…

STM32入门指南:了解STM32

1. 初识 STM32 STM32&#xff0c;从字面上来理解&#xff0c;ST 是意法半导体&#xff0c;M 是 Microelectronics 的缩写&#xff0c;32 表示 32 位&#xff0c;合起来理解&#xff0c;STM32 就是指 ST 公司开发的 32 位微控制器。在如今的 32 位控制器当中&#xff0c;STM32 …

GitHub新建仓库 上传文档

Author:龙箬 Computer Application Technology Change the World with Data and Artificial Intelligence ! CSDNweixin_43975035 振&#xff0c;而飞破虚空 点击New repository 自定义仓库名称&#xff0c;并勾选 “Add a README file” 选项 复制Code链接 打开终端Git git cl…

夏驰和徐策带你从零开始学数据结构——哈希表

哈希表的概念&#xff1a; 哈希表是一种常用的数据结构&#xff0c;它可以在 O(1) 的时间复杂度内执行插入、查找和删除操作。哈希表的核心思想是使用哈希函数将键值对映射到数组中的一个位置上&#xff0c;从而实现快速的访问和修改。 哈希表由两个主要部分组成&#xff1a;…

Android开发—入门Kotlin编程语言

一、Kotlin简介 为什么Kotlin能代替Java此为Android官方第一支持的开发语言&#xff1f; 1&#xff09;Kotlin的语法更加简洁&#xff0c;对于同样的功能&#xff0c;使用Ktolin开发的代码量可能会比使用Java开发减少50%甚至更多&#xff1b; 2&#xff09;Kotlin语法更加高…

【Linux】文件IO---应用开发角度

目录简述 目录 前言&#xff1a; 一、Linux的文件 二、Linux文件系统目录结构 三、文件访问的方式 &#xff08;1&#xff09;通用方式&#xff1a;open/read/write/lseek/close 示例&#xff1a; &#xff08;2&#xff09;非通用函数&#xff1a;ioctl/mmap 示例&am…

使用ChatGPT+MindShow一键生成PPT,以后再也不用担心制作PPT啦

&#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是阿牛&#xff0c;全栈领域优质创作者。&#x1f61c;&#x1f4dd; 个人主页&#xff1a;馆主阿牛&#x1f525;&#x1f389; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4d…

深度学习及使用全连接神经网络实现手写数字识别案例开发

1.什么是深度学习和机器学习有什么区别&#xff1f;是什么原因使得部分问题机器学习无法解决需要深入研究深度学习&#xff1f; 人工智能、机器学习、深度学习的区别是什么&#xff1f;_哔哩哔哩_bilibili 深度学习是一种机器学习方法&#xff0c;它通过构建多层神经网络来实…

tmall.product.template.get( 产品接口 )

&#xffe5;免费必须用户授权 产品模板获取接口&#xff0c;对于非关键属性的类目&#xff0c;发布达尔文(监管)产品时&#xff0c;必须先根据类目获取产品模板。 产品模板定义产品发布需要的类目属性&#xff0c;包括&#xff1a; 关键属性:关键属性可以在类目上不存在。不…

spring的应用 xml配置实现定时任务

定时任务的实现&#xff1a; 通过xml实现&#xff1a; 创建qiuckstart的maven文件 把依赖配置改改 jdk1.8 以及12 再删掉一些不必要的配置 引入spring依赖坐标 和java同一个目录下创建resources 作为 资源根 结构如图&#xff1a; spring.xml配置&#xff1a; 从官网复制…

《JavaEE》网络中的基本概念

&#x1f451;作者主页&#xff1a;Java冰激凌 &#x1f4d6;专栏链接&#xff1a;JavaEE 局域网/广域网 在我们的生活中 经常会使用到网络 对于网络 我们现在已经变得与生活息息相关 甚至可以说为密不可分 而在我们的网络中 我们的网络是分为局域网与广域网 我们的局域网和广域…

【8086汇编】环境搭建 - 学习笔记:WIN10下安装配置 MASMPlus + DOSBox

【8086汇编】环境搭建 - 学习笔记&#xff1a;WIN10下安装配置 MASMPlus DOSBox 一、MASMPlus 1.2下载安装 二、DOSBox 0.74-3下载安装配置自动挂载C盘添加环境变量 三、masm v5.0四、ml.exe v6.11参考资料 一、MASMPlus 1.2 下载 脚本之家&#xff1a;MASMPlus(汇编开发环境…

【深度学习】第六阶段

1、超参数调试 在深度学习中&#xff0c;有各种各样的超参数&#xff0c;其中包括&#xff1a;学习率 α \alpha α、动量超参数 β \beta β、Adam中的超参数 β 1 \beta_1 β1​、 β 2 \beta_2 β2​和 ε \varepsilon ε、神经网络层数、每层的结点数量、 小样本数据集大小…

mlq color transfer: Color Transfer Using Probabilistic Moving Least Squares

文章目录 Color Transfer Using Probabilistic Moving Least Squares1. 颜色转换2. 如何计算匹配点的概率3. 核心思想和具体操作&#xff1a;4. 特征点覆盖不到的颜色4.1这里介绍一下引文7&#xff1a;4.2. 分析 5. Probabilistic Moving Least Squares with Spatial Constrain…