c 读取数据库-c# 读取excel数据
前言
本文总结了一些常见的在线应急现象以及相应的排查步骤和工具。 分享的主要目的是让接触线上问题不多的同学有个预知,以免遇到实际问题手忙脚乱。 毕竟,作者本人也来自匆忙的时代。
在这里只是提醒一下。 请记住,在发生在线紧急情况时,只有一个总体目标:尽快恢复服务并消除影响。 无论处于哪个应急阶段,我们首先要思考的就是恢复问题。 恢复问题可能无法定位问题,也可能没有完美的解决方案。 可能是凭经验判断的,也可能是预置开关等,但可能会使问题变得更糟。 我们达到快速恢复的目的,然后保留部分站点,然后再去定位问题,解决问题,盘盘。
大部分情况下,我们优先先恢复服务,保留当时的异常信息(内存转储、线程转储、gc日志等,紧急情况下,你甚至不需要保留,等着吧之后再重现),等到服务正常了,再去重置问题。
好的,现在让我们进入正题。
常见症状:高/峰值 CPU 利用率
场景预设:
监控系统突然报警,服务器负载异常。
前面:
CPU飙升只是一种现象,具体问题可能有很多种。 这里我只是用这个现象来切入。
注:CPU占用率是衡量系统繁忙程度的重要指标。 但是CPU使用率的安全阈值是相对的,取决于你的系统是IO密集型还是计算密集型。 一般来说,计算密集型应用的CPU占用率高,负载低,而IO密集型应用则相反。
常见原因:
模拟
这里为了演示,用最简单的死循环来模拟CPU飙升的场景。 下面是模拟代码,
在最简单的SpringBoot Web项目中添加CpuReaper类,
/** * 模拟 cpu 飙升场景 * @author Richard_yyf */@Componentpublic class CpuReaper { @PostConstruct public void cpuReaper() { int num = 0; long start = System.currentTimeMillis() / 1000; while (true) { num = num + 1; if (num == Integer.MAX_VALUE) { System.out.println("reset"); num = 0; } if ((System.currentTimeMillis() / 1000) - start > 1000) { return; } } }}
打包成jar后,在服务器上运行。 java -jar cpu-reaper.jar &
第一步:定位问题线程方法a:传统方法top定位CPU最高的进程执行top命令,查看所有进程占用系统CPU的顺序,定位是哪个进程负责。 在这种情况下,它是我们的 java 进程。 PID 列是进程号。 (指标含义不清楚见【附录】) top -Hp pid定位使用CPU最高的线程 printf '0x%x' tid 线程id转换十六进制>printf'0x%x'12817>0x3211jstack pid | grep tid 查找线程堆栈 > jstack 12816 | grep 0x3211 -A 30 方法 b: show-busy-java-threads
这个脚本来自github上的一个开源项目,它提供了很多有用的脚本,show-busy-java-threads就是其中之一。 使用这个脚本,可以直接简化方法A中繁琐的步骤。 如下,
> wget --no-check-certificate https://raw.github.com/oldratlee/useful-scripts/release-2.x/bin/show-busy-java-threads> chmod +x show-busy-java-threads> ./show-busy-java-threads
show-busy-java-threads# 从所有运行的Java进程中找出最消耗CPU的线程(缺省5个),打印出其线程栈# 缺省会自动从所有的Java进程中找出最消耗CPU的线程,这样用更方便# 当然你可以手动指定要分析的Java进程Id,以保证只会显示你关心的那个Java进程的信息show-busy-java-threads -p <指定的Java进程Id> show-busy-java-threads -c <要显示的线程栈数>
方法c:artha线程
阿里开源的arthas几乎接手了我们线上的排查工作,提供了一套非常完善的工具。 在这种情况下,只需要一个 thread -n 命令。
> curl -O https://arthas.gitee.io/arthas-boot.jar # 下载
需要注意的是,arthas的cpu ratio与前面两次cpu ratio统计不同。 前两个针对的是Java进程启动到现在的CPU占比。 Arthas是一个采样区间内当前JVM中每个线程占用的CPU时间占总CPU时间的百分比。
详情见官网:
跟进
通过第一步,找到有问题的代码后,观察线程栈后。 具体问题具体分析。 这里有一些例子。
Case 1:发现GC线程使用了最高的CPU。
GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007fd99001f800 nid=0x779 runnableGC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007fd990021800 nid=0x77a runnable GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007fd990023000 nid=0x77b runnable GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007fd990025000 nid=0x77c runnabl
gc查的比较多,所以决定后面单独写一节。
情况二:发现占用CPU最多的业务线程在等待内核态锁,比如synchronized 常见现象:频繁GC 1.回顾GC流程
在理解下面的内容之前,请花点时间回顾一下GC的整个过程。
接上前面的内容,在这种情况下,我们很自然地想到查看gc的具体情况。
这里补充说明开启gc log。 一个经常被讨论(惰性思维)的问题是生产环境是否应该开启GC logging。 由于它产生的开销通常非常有限,我的回答是需要打开它。 但是启动JVM时不需要指定GC日志参数。
HotSpot JVM 有一类特殊的参数,称为可管理参数。 对于这些参数c 读取数据库,可以在运行时修改它们的值。 我们在这里讨论的所有参数以及以“PrintGC”开头的参数都是可管理的参数。 这样我们就可以随时开启或关闭GC日志。 例如,我们可以使用JDK自带的jinfo工具来设置这些参数,或者通过JMX客户端调用HotSpotDiagnostic MXBean的setVMOption方法来设置这些参数。
再次在这里,arthas❤️受到高度赞扬。 它提供的vmoption命令可以直接查看和更新VM诊断相关的参数。
获取gc日志后,可以上传到GC easy帮助分析,得到可视化图表分析结果。
2. GC的原因和位置
推广失败
从S区提升出来的对象不能放到老年代,导致FullGC(如果fgc回收无效,会抛出OOM)。
可能的原因:
也可以从full GC的效果来推断问题。 正常情况下,full GC应该回收大量内存,所以正常的堆内存曲线应该是锯齿状的。 如果发现Full GC后堆内存几乎没有下降,则可以推断堆中有大量对象无法回收并不断膨胀,使得堆使用比例超过触发阈值full GC,但是不能回收,导致Full GC一直执行。 换句话说,它可能是内存泄漏。
一般来说,GC相关的异常推断需要涉及到内存分析。 使用jmap等工具转储内存快照(或Arthas heapdump)命令,然后使用MAT、JProfiler、JVisualVM等可视化内存分析工具。
至于内存分析后的步骤,需要根据具体问题具体分析。
常见现象:线程池异常
场景预设:
业务监控突然报警c 读取数据库,或者外部反馈提示大量请求执行失败。
异常说明:
Java线程池以有界队列的线程池为例。 提交新任务时,如果正在运行的线程数小于corePoolSize,则创建一个新线程来处理请求。 如果正在运行的线程数等于 corePoolSize,则将新任务添加到队列中,直到队列满为止。 当队列满时,会继续创建新的线程来处理任务,但不会超过maximumPoolSize。 当任务队列已满,已经开启了最大线程数,又有新的任务到来时,ThreadPoolExecutor会拒绝服务。
常见问题和原因
这种线程池异常一般在开发的时候可以通过查看日志发现。 有几个原因:
下游服务响应时间(RT)过长。 这种情况可能是下游服务异常导致的。 作为消费者,我们需要设置合适的超时时间和断路器降级机制。 另外,对于这种情况,一般需要有相应的监控机制:比如日志监控,metrics监控告警等,不要等到目标用户感觉异常,从外部反馈了问题,才去查看日志。数据库慢sql或数据库死锁
查看日志中的相关关键字。
Java 代码死锁 jstack –l pid | grep -i –E '阻塞 | deadlock' 4.恢复常见问题
这部分内容引用自本文
对于上面提到的一些问题,这里有一些恢复方法。
5.阿尔萨斯
这里我还是想在单独的一节中使用Arthas工具。
Arthas 是阿里巴巴开源的 Java 诊断工具。 Arthas在Java Agent方式的基础上,使用Instrumentation方式修改字节码,进行Java应用诊断。
以上内容摘自Arthas官方文档。
此外,Arthas还集成了ognl这个轻量级的表达式引擎,通过ognl,你可以使用arthas实现很多“秀”的操作。
其他的我这里就不多说了。 有兴趣的可以去看看arthas的官方文档和github issue。
6.涉及的工具
让我们谈谈一些工具。
结语
我知道我这篇文章对线上异常的总结并不全面,网络(超时,TCP队列溢出...),堆外内存等很多异常场景都没有涵盖。 主要是我接触的少,对它没有深入的了解。 强行写出来,差点漏掉,更怕误会别人。
还有一点我想说的是,网上考察Java应用,其实很讲究一个人的基础是否扎实,解决问题的能力是否好。 比如线程池运行机制、gc分析、Java内存分析等,如果基础不扎实,会比较迷茫。 另外,多看网上一些结合实际场景排查异常的经验文章,学习他们排查问题的思路和工具。 这样即使暂时不能满足,我也会在脑海中慢慢总结出一套解决类似问题的结构框架。 真正遇到的时候,也只是推论罢了。
top命令显示的指标含义
指标
意义
PID
进程号
用户
流程负责人
公关
进程优先级
你
nice值。负值表示高优先级,正值表示低优先级
虚实
进程使用的虚拟内存总量,以 kb 为单位。 VIRT=SWAP+RES
RES
进程使用但未换出的物理内存大小,以 kb 为单位。 RES=代码+数据
SHR
共享内存大小,单位kb
小号
过程状态。 D=不间断睡眠 R=运行 S=睡眠 T=跟踪/停止 Z=僵尸进程
%中央处理器
自上次更新以来占用的 CPU 时间百分比
%内存
进程使用的物理内存百分比
时间+
进程使用的CPU总时间,单位1/100秒
命令
进程名(命令名/命令行)