原创

SpringBoot-线上服务卡死卡顿分析-http请求进不去服务-调整tomcat-undertow线程数



线程监控工具查看 stack.log文件
查内存镜像和阻塞情况:
java调优相关:来源:https://gitee.com/jiangjiesheng/java-optimization-and-debug-for-prod-env
jps -l 查看当前系统运行了哪些Java进程【给出进程号和包名】
jstat 查看jvm统计信息(好像没啥实际的作用)
jmap 手动导出内存镜像文件用于内存溢出分析
(结合jps -l 或ps -ef | grep 查到进程号)
jmap -dump:format=b,file=java_pid9544_by_jmap.hprof 9544,
也可以通过参数自动导出 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./export/
分析工具:MemoryAnalyzer.exe(MAT工具)
jstack 实战死循环与死锁 ,由阻塞方法引起的死锁,看起来不动了【实用】
jstack -F 进程号 > jstack.deadlock.10892.txt # -F参数可以强制导出
或者 jstack -l 进程号 | grep deadlocks 进程号,直接展示结果。
报告中搜索 deadlock 关键词,如果没有死锁 No deadlocks found。
如果报告中有 Thread 1783: (state = BLOCKED),这个怎么定位?结合服务的log日志中线程号来定位?
不处理的危害可能导致java占用内存越来越大,这个时候就需要去脚本限制内存大小了
jstack 8 > stack.log
查SQL情况:
mysql -hmysql -umaster -ppZdxysqJX4bK4VrB -A
edu:
use seats
SELECT trx_mysql_thread_id,trx_query FROM INFORMATION_SCHEMA.INNODB_TRX
where trx_mysql_thread_id in (select id from information_schema.processlist where command != 'Sleep' )
and (trx_query like "%course%" or trx_query like "%edu%" or trx_query like "%exam%" or trx_query like "%inte%")\G
如何排查java程序导致的cpu和内存过高异常
https://blog.csdn.net/qq_40322236/article/details/127223538
打印gc日志:
-Dlogin.cache.switch=true -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps
-XX:+DisableExplicitGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./

undertow设置:
-DinvokeSeconds=60 -Dserver.undertow.io-threads=16 -Dserver.undertow.worker-threads=500
server:
undertow:
io-threads: 16
worker-threads: 500
实测:无效,断点看相关的初始化还是按默认的计算规则走的

tomcat设置:
-Dserver.tomcat.max-threads=500 -Dserver.tomcat.max-connections=20000
-Dserver.tomcat.accept-count=2000 -Dserver.tomcat.min-spare-threads=20

下次卡的时候 再看线程
另外看undertow的 java.lang.Thread.State: TIMED_WAITING (parking)

处理1
通过代码初始化线程数,debug初始化有效
package cn.jiangjiesheng.edu.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class UndertowConfig {
@Value(value = "${server.undertow.io-threads:16}")
private Integer ioThreads;
@Value(value = "${server.undertow.worker-threads:500}")
private Integer workerThreads;

@Bean
public UndertowServletWebServerFactory embeddedServletContainerFactory() {
UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();
factory.setIoThreads(ioThreads);
factory.setWorkerThreads(workerThreads);
return factory;
}
}

处理2:
加锁方式,调试不同人员的学习 会 触发 同一个课程id的数据同步,
所以同一课程处理处理过程中要排除掉进来的其他请求【可能也有问题,极低概率下正好错过了】

concurrentTaskBySingleKeyExecutor.doTask("syncEduTrainImplementRecordDetailService
#insertOrUpdateCourse", implementId + "#courseId" + courseId, new Runnable() {


网络资料:
https://www.zhihu.com/tardis/bd/art/401186598?source_id=1001
【关键,但是参数设置,不生效,要用代码初始化,根据断点看Undertow的初始化】

debug关键代码:
private Undertow(Builder builder) {
...
this.ioThreads = builder.ioThreads;
this.workerThreads = builder.workerThreads;
...
}

public synchronized void start() {
UndertowLogger.ROOT_LOGGER.infof("starting server: %s", Version.getFullVersionString());
xnio = Xnio.getInstance(Undertow.class.getClassLoader());
channels = new ArrayList<>();
try {
if (internalWorker) {
worker = xnio.createWorker(OptionMap.builder()
.set(Options.WORKER_IO_THREADS, ioThreads)
.set(Options.CONNECTION_HIGH_WATER, 1000000)
.set(Options.CONNECTION_LOW_WATER, 1000000)
.set(Options.WORKER_TASK_CORE_THREADS, workerThreads)
.set(Options.WORKER_TASK_MAX_THREADS, workerThreads)
.set(Options.TCP_NODELAY, true)
.set(Options.CORK, true)
.addAll(workerOptions)
.getMap());
}
....
}

public static final class Builder {

private int ioThreads;
private int workerThreads;
private Builder() {
ioThreads = Math.max(Runtime.getRuntime().availableProcessors(), 2);
workerThreads = ioThreads * 8;
long maxMemory = Runtime.getRuntime().maxMemory();
//smaller than 64mb of ram we use 512b buffers
if (maxMemory < 64 * 1024 * 1024) {
//use 512b buffers
directBuffers = false;
bufferSize = 512;
} else if (maxMemory < 128 * 1024 * 1024) {
//use 1k buffers
directBuffers = true;
bufferSize = 1024;
} else {
//use 16k buffers for best performance
//as 16k is generally the max amount of data that can be sent in a single write() call
directBuffers = true;
bufferSize = 1024 * 16 - 20; //the 20 is to allow some space for protocol headers, see UNDERTOW-1209
}
}


public Builder setIoThreads(final int ioThreads) {
this.ioThreads = ioThreads;
return this;
}

public Builder setWorkerThreads(final int workerThreads) {
this.workerThreads = workerThreads;
return this;
}
}

更多网络资料:
https://blog.csdn.net/weixin_43958014/article/details/129684017
https://www.lxiaoyu.com/p/161092
https://www.cnblogs.com/koal/p/12347982.html
https://blog.csdn.net/tiandixuanwuliang/article/details/102733441
https://www.ibm.com/support/pages/ibm-thread-and-monitor-dump-analyzer-java-tmda
正文到此结束
本文目录