深圳建设局网站宝安分中心,苏州关键词优化平台,湖南住房和城乡建设网站,今天的新闻头条最新消息#x1f44f;作者简介#xff1a;大家好#xff0c;我是爱吃芝士的土豆倪#xff0c;24届校招生Java选手#xff0c;很高兴认识大家#x1f4d5;系列专栏#xff1a;Spring源码、JUC源码#x1f525;如果感觉博主的文章还不错的话#xff0c;请#x1f44d;三连支持作者简介大家好我是爱吃芝士的土豆倪24届校招生Java选手很高兴认识大家系列专栏Spring源码、JUC源码如果感觉博主的文章还不错的话请三连支持一下博主哦博主正在努力完成2023计划中源码溯源一探究竟联系方式nhs19990716加我进群大家一起学习一起进步一起对抗互联网寒冬 文章目录 定位问题1.慢查询日志2.监控压测监控核心指标系统性能指标交易响应时间系统处理能力错误率 资源指标CPUMemory磁盘吞吐量网络吞吐量 中间件指标数据库指标稳定性指标可扩展性指标 3.链路追踪 问题排查1.个别接口响应慢链路追踪在链路上打印日志死锁问题定位死锁jpsjconsole 2.所有接口响应慢CPU占用过高内存占用过高磁盘问题网络问题垃圾回收 定位问题
1.慢查询日志
通常情况下为了定位sql的性能瓶颈我们需要开启mysql的慢查询日志。把超过指定时间的sql语句单独记录下来方面以后分析和定位问题。
开启慢查询日志需要重点关注三个参数
slow_query_log 慢查询开关slow_query_log_file 慢查询日志存放的路径long_query_time 超过多少秒才会记录日志
通过mysql的set命令可以设置
set global slow_query_logON;
set global slow_query_log_file/usr/local/mysql/data/slow.log;
set global long_query_time2;设置完之后如果某条sql的执行时间超过了2秒会被自动记录到slow.log文件中。
当然也可以直接修改配置文件my.cnf
[mysqld]
slow_query_log ON
slow_query_log_file /usr/local/mysql/data/slow.log
long_query_time 2但这种方式需要重启mysql服务。
2.监控
可观测性帮助企业在复杂的分布式系统中更加快速的排查、定位问题已经是分布式系统中必不可少的运维工具。
可观测性从传统监控场景不断延伸逐渐覆盖 Metrics、Traces、Logs 三个维度并将之相互融合。在性能压测领域中可观测性更为重要除了有助于定位性能问题其中 Metrics 性能指标更直接决定了压测是否通过系统最终是否可以上线具体如下
Metrics - 监控指标
系统性能指标包括请求成功率、系统吞吐量、响应时长
资源性能指标衡量系统软硬件资源使用情况配合系统性能指标观察系统资源水位
Logs - 日志
施压引擎日志观察施压引擎是否健康压测脚本执行是否有报错
采样日志采样记录API的请求和响应详情辅助排查压测过程中的一些出错请求的参数是否正常并通过响应详情查看完整的错误信息
Traces - 分布式链路追踪
用于性能问题诊断阶段通过追踪请求在系统中的调用链路定位报错 API 的报错系统和报错堆栈快速定位性能问题点。
压测监控核心指标
压测过程中对系统硬件、中间件、数据库资源的监控也很重要包括系统性能指标、资源指标、中间件指标、数据库指标、前端指标、稳定性指标、批量处理指标、可扩展性指标、可靠性指标等。
系统性能指标
交易响应时间
定义 响应时间指用户从客户端发起一个请求开始到客户端接收到从服务器端返回的响应结束整个过程所耗费的时间。在性能检测中一般以压力发起端至被压测服务器返回处理结果的时间为计量单位一般为秒或毫秒。平均响应时间指系统稳定运行时间段内同一交易的平均响应时间。一般而言交易响应时间均指平均响应时间。
简称 Response Time: RT
参考标准不同行业不同业务可接受的响应时间是不同的 互联网企业500 毫秒以下例如淘宝业务 10 毫秒左右 金融企业1 秒以下为佳部分复杂业务 3 秒以下 保险企业3 秒以下为佳 制造业5 秒以下为佳 时间窗口即整个压测过程的时间不同数据量则时间不一样例如双 11 和 99 大促数据量级不一样则时间窗口不同。大数据量的情况下2 小时内可完成压测
系统处理能力
定义 系统处理能力是指系统在利用系统硬件平台和软件平台进行信息处理的能力。系统处理能力通过系统每秒钟能够处理的交易数量来评价是技术测试活动中重要指标
简称一般情况下用以下指标来度量 HPSHits Per Second 每秒点击次数单位是次/秒 TPSTransaction per Second系统每秒处理交易数单位是笔/秒。 QPSQuery per Second系统每秒处理查询次数单位是次/秒。对于互联网业务中如果某些业务有且仅有一个请求连接那么 TPSQPSHPS一般情况下用 TPS 来衡量整个业务流程用 QPS 来衡量接口查询次数用 HPS 来表示对服务器单击请求
标准无论 TPS、QPS、HPS此指标是衡量系统处理能力非常重要的指标越大越好根据经验一般情况下 金融行业1000 TPS~50000 TPS不包括互联网化的活动 保险行业100 TPS~100000 TPS不包括互联网化的活动 制造行业10 TPS~5000 TPS 互联网电子商务10000 TPS~1000000 TPS 互联网中型网站1000 TPS~50000 TPS 互联网小型网站500 TPS~10000 TPS
错误率
定义 错误率指系统在负载情况下失败交易的概率。错误率失败交易数/交易总数×100%。稳定性较好的系统其错误率应该由超时引起即为超时率。
标准不同系统对错误率的要求不同但一般不超出千分之六即成功率不低于 99.4%
资源指标
CPU
定义 中央处理器是一块超大规模的集成电路是一台计算机的运算核心Core和控制核心 Control Unit。它的功能主要是解释计算机指令以及处理计算机软件中的数据。
Memory
定义 内存是计算机中重要的部件之一它是与 CPU 进行沟通的桥梁。计算机中所有程序的运行都是在内存中进行的因此内存的性能对计算机的影响非常大
磁盘吞吐量
定义 磁盘吞吐量是指在无磁盘故障的情况下单位时间内通过磁盘的数据量
网络吞吐量
定义 网络吞吐量是指在无网络故障的情况下单位时间内通过的网络的数据数量。单位为 Byte/s。网络吞吐量指标用于衡量系统对于网络设备或链路传输能力的需求。当网络吞吐量指标接近网络设备或链路最大传输能力时则需要考虑升级网络设备
中间件指标 数据库指标 数据库监控中的命中率通常指的是缓存命中率它表示在数据库访问中请求能够从缓存中获取所需数据的比例。换句话说命中率越高就意味着数据库查询所需的数据越多地可以从缓存中获取而不需要去访问磁盘或进行其他昂贵的操作。这通常被认为是一个性能指标因为高命中率通常意味着更快的响应时间和更好的系统性能。
稳定性指标
定义 最短稳定时间系统按照最大容量的 80% 或标准压力系统的预期日常压力情况下运行能够稳定运行的最短时间。一般来说对于正常工作日8小时运行的系统至少应该能保证系统稳定运行小时以上。对于 7×24 运行的系统至少应该能够保证系统稳定运行 24 小时以上。如果系统不能稳定的运行上线后随着业务量的增长和长时间运行将会出现性能下降甚至崩溃的风险
标准
TPS 曲线稳定没有大幅度的波动各项资源指标没有泄露或异常情况
可扩展性指标
定义 指应用软件或操作系统以集群方式部署增加的硬件资源与增加的处理能力之间的关系。计算公式为增加性能/原始性能/增加资源/原始资源×100%。扩展能力应通过多轮测试获得扩展指标的变化趋势。一般扩展能力非常好的应用系统扩展指标应是线性或接近线性的现在很多大规模的分布式系统的扩展能力非常好。
标准
理想的扩展能力是资源增加几倍性能就提升几倍。扩展能力至少在70%以上。
目前业界使用比较多的开源监控系统是Prometheus。
它提供了 监控 和 预警 的功能。
我们可以用它监控如下信息
接口响应时间调用第三方服务耗时慢查询sql耗时cpu使用情况内存使用情况磁盘使用情况数据库使用情况
它的界面大概长这样子 可以看到mysql当前qps活跃线程数连接数缓存池的大小等信息。
如果发现数据量连接池占用太多对接口的性能肯定会有影响。
这时可能是代码中开启了连接忘了关或者并发量太大了导致的需要做进一步排查和系统优化。
3.链路追踪
有时候某个接口涉及的逻辑很多比如查数据库、查redis、远程调用接口发mq消息执行业务代码等等。
该接口一次请求的链路很长如果逐一排查需要花费大量的时间这时候我们已经没法用传统的办法定位问题了。
有没有办法解决这问题呢
用分布式链路跟踪系统skywalking。
通过skywalking定位性能问题 在skywalking中可以通过traceId全局唯一的id串联一个接口请求的完整链路。可以看到整个接口的耗时调用的远程服务的耗时访问数据库或者redis的耗时等等功能非常强大。
之前没有这个功能的时候为了定位线上接口性能问题我们还需要在代码中加日志手动打印出链路中各个环节的耗时情况然后再逐一排查。
问题排查
1.个别接口响应慢
链路追踪
使用SkyWalking展示出每一个与网络有关的耗时。比如读写数据库、读写Redis、SpringCloud调用、Dubbo调用等。这样就能立马定位是哪次操作耗时了。
同时SkyWalking可以记录每一个SQL语句可以帮助定位。
例如如箭头所指处最上边一个是总耗时下边的线段是单个操作的耗时 在链路上打印日志
在相应的链路上打印日志然后查看日志看是哪个地方耗时。
死锁问题
在这里重点讲一下出现死锁问题的排查经验吧
有这样的情况一个线程需要同时获取多把锁这时就容易发生死锁
t1 线程 获得 A对象 锁接下来想获取 B对象 的锁 t2 线程 获得 B对象 锁接下来想获取 A对象 的锁
Object A new Object();Object B new Object();Thread t1 new Thread(() - {synchronized (A) {log.debug(lock A);sleep(1);synchronized (B) {log.debug(lock B);log.debug(操作...);}}}, t1);Thread t2 new Thread(() - {synchronized (B) {log.debug(lock B);sleep(0.5);synchronized (A) {log.debug(lock A);log.debug(操作...);}}}, t2);t1.start();t2.start();
12:22:06.962 [t2] c.TestDeadLock - lock B
12:22:06.962 [t1] c.TestDeadLock - lock A 定位死锁
检测死锁可以使用 jconsole工具或者使用 jps 定位进程 id再用 jstack 定位死锁
jps
cmd jps
Picked up JAVA_TOOL_OPTIONS: -Dfile.encodingUTF-8
12320 Jps
22816 KotlinCompileDaemon
33200 TestDeadLock // JVM 进程
11508 Main
28468 Launchercmd jstack 33200Picked up JAVA_TOOL_OPTIONS: -Dfile.encodingUTF-82018-12-29 05:51:40Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.91-b14 mixed mode):DestroyJavaVM #13 prio5 os_prio0 tid0x0000000003525000 nid0x2f60 waiting on condition[0x0000000000000000]java.lang.Thread.State: RUNNABLEThread-1 #12 prio5 os_prio0 tid0x000000001eb69000 nid0xd40 waiting for monitor entry[0x000000001f54f000]java.lang.Thread.State: BLOCKED (on object monitor)at thread.TestDeadLock.lambda$main$1(TestDeadLock.java:28)- waiting to lock 0x000000076b5bf1c0 (a java.lang.Object)- locked 0x000000076b5bf1d0 (a java.lang.Object)at thread.TestDeadLock$$Lambda$2/883049899.run(Unknown Source)at java.lang.Thread.run(Thread.java:745)Thread-0 #11 prio5 os_prio0 tid0x000000001eb68800 nid0x1b28 waiting for monitor entry[0x000000001f44f000]java.lang.Thread.State: BLOCKED (on object monitor)at thread.TestDeadLock.lambda$main$0(TestDeadLock.java:15)- waiting to lock 0x000000076b5bf1d0 (a java.lang.Object)- locked 0x000000076b5bf1c0 (a java.lang.Object)at thread.TestDeadLock$$Lambda$1/495053715.run(Unknown Source)at java.lang.Thread.run(Thread.java:745)// 略去部分输出Found one Java-level deadlock:Thread-1:waiting to lock monitor 0x000000000361d378 (object 0x000000076b5bf1c0, a java.lang.Object),which is held by Thread-0Thread-0:waiting to lock monitor 0x000000000361e768 (object 0x000000076b5bf1d0, a java.lang.Object),which is held by Thread-1Java stack information for the threads listed above:Thread-1:at thread.TestDeadLock.lambda$main$1(TestDeadLock.java:28)- waiting to lock 0x000000076b5bf1c0 (a java.lang.Object)- locked 0x000000076b5bf1d0 (a java.lang.Object)at thread.TestDeadLock$$Lambda$2/883049899.run(Unknown Source)at java.lang.Thread.run(Thread.java:745)Thread-0:at thread.TestDeadLock.lambda$main$0(TestDeadLock.java:15)- waiting to lock 0x000000076b5bf1d0 (a java.lang.Object)- locked 0x000000076b5bf1c0 (a java.lang.Object)at thread.TestDeadLock$$Lambda$1/495053715.run(Unknown Source)at java.lang.Thread.run(Thread.java:745)Found 1 deadlock
这里是两个线程 “Thread-0” 和 “Thread-1” 在互相等待对方释放锁从而导致了死锁。
线程 “Thread-1” 试图获取对象0x000000076b5bf1c0的监视器锁即synchronized关键字保护的那个对象但是这个锁已经被线程 “Thread-0” 持有。因此“Thread-1” 进入了等待状态等待 “Thread-0” 释放这个锁。
同时线程 “Thread-0” 试图获取对象0x000000076b5bf1d0的监视器锁但是这个锁已经被线程 “Thread-1” 持有。因此“Thread-0” 进入了等待状态等待 “Thread-1” 释放这个锁。
jconsole 2.所有接口响应慢
如果线上出了问题首先判断是业务问题还是整个系统的问题。如果是业务问题就去看应用的日志等进行排查。如果出现了如下问题就可能是整个系统的问题
大量接口都很慢页面打不开
如何得知系统出问题了
系统出问题时我们需要进行详细排查一般情况下有以下场景我们可以得知线上出问题了
用户反馈功能不能正常使用监控系统的邮件或者短信提醒
系统问题排查步骤
以下按顺序进行
是否CPU占用过高是否内存占用过高是否磁盘占用过高是否网络故障查看后台日志是否是数据库问题比如索引失效、死锁是否是垃圾回收导致
CPU占用过高
什么场景需要排查CPU占用
访问接口的响应速度很慢。系统崩溃无响应压测时要查看CPU、内存、load、rt、qps等指标
步骤简述
定位进程 命令top定位线程 命令top -Hp 进程号定位代码位置 命令jstack
排查方法详述
找到占CPU最高的进程。 top命令记下进程号PID。假设最高的是1893 通过进程找到对应的线程。 top -Hp 1893。假设最高的是4519因为Java是单进程多线程的 通过线程定位到代码大概的位置信息。 printf %x 4519。结果为11a7jstack 1893 | grep 11a7 -A 30 –color 结果大概是这样的 可能导致CPU使用率飙升的操作
无限循环的while经常使用Young GC频繁的GC
如果访问量很高可能会导致频繁的GC甚至Full GC。当调用量很大时内存分配将如此之快以至于GC线程将连续执行这将导致CPU飙升。
序列化和反序列化
序列化和反序列化本身不会导致CPU使用率飙升。序列化是将对象转换为字节流的过程而反序列化则是将字节流转换回对象的过程。这两个过程通常在内存中完成并不直接导致CPU使用率的飙升。
然而在某些情况下序列化和反序列化可能会导致CPU使用率增加。例如当需要大量的数据进行序列化或反序列化时可能会消耗较多的CPU资源。此外如果序列化和反序列化的操作频繁且耗时较长也可能对CPU使用率产生一定影响。
正则表达式
正则表达式本身不会导致CPU飙升但是使用不当或者复杂的正则表达式可能会导致CPU负载增加。
正则表达式在处理大量文本时特别是复杂的表达式或者需要进行大量回溯的情况下可能会消耗大量的 CPU 资源。这是因为正则表达式引擎需要在文本中进行搜索和匹配并且有些复杂的规则可能需要大量的计算才能找到匹配的结果。
因此在编写正则表达式时需要注意避免过于复杂或低效的表达式尤其是在处理大量文本的场景下。另外对于一些需要频繁执行的操作可以考虑在代码中进行优化以减少对 CPU 的负载影响。
线程上下文切换
内存占用过高
步骤简述
定位Java程序内存使用过高或者内存泄漏的问题跟CPU也类似可分为以下步骤
定位进程 命令top定位线程 命令top -Hp 进程号定位代码位置 命令jmap生成快照MAT / jprofiler / VisualVM / jhat 查看快照数据
1.定位进程
top按下M按内存占用由大到小排序 // 假设定位到的进程ID为14279。
2.定位线程
top -Hp 14279;
按下M按内存占用由大到小排序
top - 18:33:07 up 25 days, 7:48, 1 user, load average: 0.17, 0.27, 0.23
Threads: 54 total, 1 running, 53 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.5 us, 0.7 sy, 0.0 ni, 98.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 8168236 total, 231696 free, 3660496 used, 4276044 buff/cache
KiB Swap: 969964 total, 969964 free, 0 used. 4197860 avail MemPID USER PR NI VIRT RES SHR S %CPU %MEM TIME COMMAND
14293 weiping 20 0 4508772 97036 18112 S 10 12 152:35.42 java
14279 weiping 20 0 4508772 97036 18112 S 5.0 1.2 0:00.00 java
14282 weiping 20 0 4508772 97036 18112 S 0.0 1.2 0:00.37 java注意观察两点
线程的数量 可以看到它线程数是54左上角的Threads项属于正常。若比较大比如大于1000要考虑是不是代码有问题 是不是代码里手动起了多个线程。比如使用OkHttpClient时每次都创建了连接池ConnectionPool应该是只创建一个连接池的。是不是自己创建的线程池最大个数太大了。 占内存大的线程的PID 如果线程数量正常就要dump内存的快照信息来查看。
3.定位代码位置
如果是线上环境注意dump之前必须先将流量切走否则大内存dump是直接卡死服务。
dump当前快照jmap -dump:formatb,filedump.hprof 14279
查找实例数比较多的业务相关的实例然后找到相应代码查看。使用工具查看dump.hprof。比如MAT、VisualVM、jhat
磁盘问题
步骤简介
是否磁盘快用完了命令df、duTPS是否正常命令iostat、vmstat、lsof
这个命令是用来检查系统的磁盘性能是否正常。具体来说
iostat 命令用于报告 CPU 使用情况和磁盘I/O统计信息。vmstat 命令用于报告虚拟内存统计信息。lsof 命令用于列出打开文件。
通过使用这些命令可以获得关于磁盘 I/O 活动、CPU 使用率、内存使用等方面的统计数据。其中磁盘 I/O 统计信息中的 TPS每秒传输的 I/O 操作数可以用来评估磁盘的性能是否正常。如果 TPS 过高或者过低可能意味着磁盘存在性能问题需要进一步分析和解决。
网络问题
垃圾回收
什么情况下GC会对程序产生影响
不管Minor GC还是FGC都会造成一定程度的程序卡顿即Stop The WorldGC线程开始工作其他工作线程被挂起即使采用ParNew、CMS或者G1这些更先进的垃圾回收算法也只是在减少卡顿时间而并不能完全消除卡顿。
那到底什么情况下GC会对程序产生影响呢根据严重程度从高到底包括以下4种情况
FGC过于频繁 FGC通常比较慢少则几百毫秒多则几秒正常情况FGC每隔几个小时甚至几天才执行一次对系统的影响还能接受。一旦出现FGC频繁比如几十分钟执行一次是存在问题的会导致工作线程频繁被停止让系统看起来一直有卡顿现象也会使得程序的整体性能变差。 YGC耗时过长 一般来说YGC的总耗时在几十或者上百毫秒是比较正常的虽然会引起系统卡顿几毫秒或者几十毫秒这种情况几乎对用户无感知对程序的影响可以忽略不计。如果YGC耗时达到了1秒甚至几秒都快赶上FGC的耗时了那卡顿时间就会增大加上YGC本身比较频繁就会导致比较多的服务超时问题。 FGC耗时过长 FGC耗时增加卡顿时间也会随之增加尤其对于高并发服务可能导致FGC期间比较多的超时问题可用性降低这种也需要关注。 YGC过于频繁 即使YGC不会引起服务超时但是YGC过于频繁也会降低服务的整体性能对于高并发服务也是需要关注的。
如何排查
公司的监控系统大部分公司都会有可全方位监控JVM的各项指标。JDK自带工具jmap、jstat 查看堆内存各区域的使用率以及GC情况jstat -gcutil pid 1000 重点关注结果中的YGC、YGCT、FGC、FGCT、GCT查看堆内存中的存活对象并按空间排序jmap -histo pid | head -n20dump堆内存文件jmap -dump:formatb,fileheap pid