Spring Boot Web 应用哀求响应太慢故障排查

打印 上一主题 下一主题

主题 866|帖子 866|积分 2598

Spring Boot Web 应用哀求响应太慢排查

线上接口响应太慢,Spring Boot + 内嵌的 Tomcat 服务器,Tomcat 处理处罚哀求的最大线程数普通情况是 150 左右,最大是 200,以是当同时处理处罚的哀求过多,而且每个哀求不停没有处理处罚完成。全部的线程都在繁忙,没有办法处理处罚新的哀求,就会导致新的哀求排队等候处理处罚,从而造成了迟迟无法响应的线上变乱,用户体验太差。
场景复现

一个简单的 controller 接口
  1. @RestController
  2. public class SpringBootController {
  3.         @GetMapping("/")
  4.         public String index() throws InterruptedException {
  5.                 // 每个线程都睡眠,模拟业务接口响应慢的问题
  6.                 Thread.sleep(60 * 30 * 1000);
  7.                 System.out.println("current thread: " + Thread.currentThread().getName());
  8.                 return "Hello Spring Boot!";
  9.         }
  10. }
复制代码
随后设置 tomcat 服务器的最大线程为 5 :
  1. server:
  2.   port: 8080
  3.   tomcat:
  4.     threads:
  5.       max: 5
  6. spring:
  7.   application:
  8.     name: simple-application
  9.    
复制代码
测试

之后我们在单元测试中模拟 10 个线程对接口发起哀求
  1. public class RequestTest {
  2.         public static void main(String[] args) {
  3.                
  4.                 for (int i = 0; i < 10; i++) {
  5.                         new Thread(new RequestTask()).start();
  6.                 }
  7.         }
  8.         private static class RequestTask implements Runnable {
  9.                 @Override
  10.                 public void run() {
  11.                         try {
  12.                                 URL url = new URL("http://localhost:8080/");
  13.                                 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
  14.                                 connection.setRequestMethod("GET");
  15.                                 int responseCode = connection.getResponseCode();
  16.                                 System.out.println("Response Code: " + responseCode);
  17.                         }
  18.                         catch (IOException e) {
  19.                                 e.printStackTrace();
  20.                         }
  21.                 }
  22.         }
  23.        
  24. }
复制代码
首先,我们解释掉 controller 中的就寝代码,运行测试得到以下的输出:
  1. spring boot web 应用响应输出:
  2. 2024-08-01T15:56:25.369+08:00  INFO 7304 --- [simple-application] [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Completed initialization in 0 ms
  3. current thread: http-nio-8080-exec-4
  4. current thread: http-nio-8080-exec-5
  5. current thread: http-nio-8080-exec-1
  6. current thread: http-nio-8080-exec-2
  7. current thread: http-nio-8080-exec-3
  8. current thread: http-nio-8080-exec-5
  9. current thread: http-nio-8080-exec-2
  10. current thread: http-nio-8080-exec-4
  11. current thread: http-nio-8080-exec-1
  12. current thread: http-nio-8080-exec-3
  13.    
  14. 测试输出:
  15. Response Code: 200
  16. Response Code: 200
  17. Response Code: 200
  18. Response Code: 200
  19. Response Code: 200
  20. Response Code: 200
  21. Response Code: 200
  22. Response Code: 200
  23. Response Code: 200
  24. Response Code: 200
复制代码
我们看到线程在响应输出。接下来,打开解释代码,模拟变乱现场。将会在控制台看不到任何输出,测试方法也会卡住不动。
排查

我们利用 JVM 的一些命令来举行排查:
  1. # 首先查看 java 的进程 id
  2. C:\Users\Administrator>jps -l
  3. 18400 indi.yuluo.tomcat.SpringBootApplication
  4. 10324 jdk.jcmd/sun.tools.jps.Jps
  5. 16872 org.jetbrains.jps.cmdline.Launcher
  6. 18072 org.jetbrains.idea.maven.server.RemoteMavenServer36
  7. 9624
  8. 7372 inid.yuluo.tomcat.RequestTest
复制代码
我们看到 SpringBootApplication 和 RequestTest 在运行,之后利用 jstack 命令生成线程快照,并保存为文件。
  1. C:\Users\Administrator>jstack 18400 > C:\Users\Administrator\Desktop\spring-boot-thread_dump.txt
复制代码
打开线程快照文件,搜索 http-nio 就能看到 Tomcat 的哀求处理处罚线程,全部的哀求处理处罚线程状态都是 TIMED_WAITING ,表示线程正在等候另一个线程实行特定的动作,但是有一个指定的等候时间。而且能直接看到哀求是壅闭在了哪个代码位置。
  1. "http-nio-8080-exec-2" #28 daemon prio=5 os_prio=0 cpu=0.00ms elapsed=187.14s tid=0x0000015ffe6089f0 nid=0x1ee4 waiting on condition  [0x00000026eb5fc000]
  2.                                                 # `TIMED_WAITING`
  3.    java.lang.Thread.State: TIMED_WAITING (sleeping)
  4.         at java.lang.Thread.sleep(java.base@17.0.1/Native Method)
  5.         # 阻塞位置:
  6.         at indi.yuluo.tomcat.controller.SpringBootController.index(SpringBootController.java:18)
复制代码
解决方案

适当修改 Tomcat 的最大线程数,可以增加并发哀求的处理处罚能力。
适当调大 Tomcat 的最小空闲线程数,可以确保在并发高峰时刻,Tomcat 能敏捷响应新的哀求,而不需要重新创建线程。
修改值需要对用户体量做出预估之后,举行测试之后确定。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

没腿的鸟

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表