在多任务系统中,次数多的事件,不一定就是性能瓶颈。所以,只观察到一个大数值,并不能说明什么问题。具体有没有瓶颈,还需要观测多个方面的多个指标,来交叉验证。
对于一个8C16G的机器来说,如果是写操作,达到500TPS应该是没有问题的。如果是读操作,还会更高,应该能达到1000TPS以上。
响应时间是用来判断业务有多快的,而 TPS 才是用来判断容量有多大的
虚拟机超分,CPU运行模式,mpstat命令,kvm管理工具virsh命令,iftop命令
st cpu 达到了 15% 左右。steal time,st cpu 是指虚拟机被宿主机上的其他应用或虚拟机抢走的 CPU,它的值这么高显然是不太正常的。所以,我们要进一步查看 st cpu 异常的原因。
top的wa指标,是指 CPU 在读写的时候,所产生的 IO 等待时间占 CPU 时间的百分比。
top -H -p 4361----查看4361进程中各线程使用 CPU 的情况
通过cat /proc/<pid>/status命令可以查看进程状态的大致信息
HTTP 是通过 Socket 来使用 TCP 的,Socket 做为套接层 API,它本身不是协议,只规定了 API
bi 是指每秒读磁盘的块数
PTR 请求------从 IP 地址反查域名
我们看到 us cpu 高,就自然地想到要去看用户级的应用栈到底在执行什么代码;当我们看到 sy cpu 高,首先想到的是去查 syscall 到底是被谁调用的。
用jstack打印一个完整的栈来看,用jvisualvm也可以,打印栈是在脚本运行时候
IBM Thread and Monitor Dump Analyzer for Java----堆栈分析工具
cut -c 5-8 cut.txt 切割cut.txt的第5-8个字符
strace -f -T -tt -p 9085
-f表示跟踪子进程和子线程,-T表示显示系统调用的时长,-tt表示显示跟踪时间
si CPU高,用cat /proc/softirqs查看软中断的具体情况
hi CPU高,用cat /proc/interrupts查看硬中断的具体情况
通过 iperf3 直接测试网络
Linux 内核中,有一个 tcp_tw_reuse 选项,用来控制端口号的重用,0为禁止,1为开启。
__init_check_established 函数的目的,是检查端口号是否可用。
ss 命令, 查看连接状态统计
timewait 状态的连接,本身会继续占用端口号。
sysctl用于在运行时修改内核参数,可用参数是/proc/sys/下列出的参数。
我们通常用网络带宽来判断网络是不是够用,但是这是不够的。你要知道,在网络中当小包过多的时候,网络带宽是难以达到线性流量的。所以,我们这里的网络带宽即便不会很高,也会导致网络软中断的增加和队列的出现。
对于性能分析来说,带宽能不能对得上非常重要。比如,客户端接收了多少流量,服务端就应该是发出了多少流量。如果服务端发了很多包,但是客户端没有接收,那就是堵在队列上了。
当我们感觉服务端没有压力的时候,一定要同时查看下网络连接和吞吐量、队列、防火墙等等信息。查看队列是非常有效的判断阻塞在哪一方的方式。
可以在 Tomcat 中加上 %D 和 %F 两个参数来记录 request 和 response 的时间。
线程池最后一个参数就是 acceptCount,表示TCP 的接收队列长度。
backlog 参数就是 Tomcat 中的 acceptCount 参数,默认值是 100
Tomcat 中的 maxConnections 是指 Tomcat 在任意时刻接收和处理的最大连接数。maxConnections 的默认值与连接器类型有关:NIO 的默认值是 10000,APR 默认是 8192。
一般来说,判断网络的时候,我们会有几个判断点。首先是带宽的流量大小,其次是,全连接和半连接队列是否已经溢出?最后是发送和接收队列是否堆积?
接收队列(Recv-Q)和发送队列(Send-Q)需要特别关注,它们通常应该是 0。当发现它们不是 0 时,说明有网络包的堆积发生。
sar 可以用来查看系统的网络收发情况,不仅可以观察网络收发的吞吐量(BPS,每秒收发的字节数),还可以观察网络收发的 PPS,即每秒收发的网络帧数。
在网络收发过程中,内核通过中断跟网卡进行交互。网卡硬中断只处理最核心的网卡数据读取或发送,而协议栈中的大部分逻辑,都会放到软中断中处理。
我们通过 SYNs to LISTEN sockets dropped 来判断半连接队列是否溢出,通过 times the listen queue of a socket overflowed 来判断全连接队列是否溢出。
一次写了多个block就显然是顺序写了;如果一次只写一个block就显然是随机写了。
如何判断磁盘是在顺序读还是随机读? --- 可以使用strace把系统调用都找出来,write是否连续就可以看到了,或者使用 blktrace 观察
为了让压力能直接压到一个节点上,我们跳过 Ingress,用分段的测法直接把压力发到服务上。然后,我们去 Pod 里设置一个 node port 把服务代理出来,再修改一下压力脚本。
火焰图应该从下往上、沿着调用栈中最宽的函数,来分析执行次数最多的函数。
CPU 使用率上升了,该怎么进行分析呢?perf配合火焰图,很容易就能找到系统中的热点函数。
只要不是 page fault 过多,我们可以先不用管物理内存。
kubectl get svc -o wide | grep xxxxx
kubectl get pods -o wide | grep xxxxx
一定要留意整个链路上有限制的点。什么是有限制的点?比如说,各种池(连接池等)、栈中的锁、数据库连接、还有数据库的锁之类。其实,总结下来就是一个关键词:阻塞。
ES data 和 ES client 都不是单一的节点,而是有几个节点。由此产生的问题就是,任意一个 ES 节点出现资源消耗过多的时候,都会影响到它所在的 worker 机器资源,进而影响到这个 ES 节点所在的整个物理机。
us cpu 高,说明确实都是业务逻辑在消耗 CPU 资源了
对于一个应用来说,us cpu 高本来就是非常合理的情况
VIP = Virtual IP Address,虚拟IP地址,主要是用来进行不同主机之间的切换,主要用在服务器的主从切换。VIP的目的是为了高可用性,为了避免单点故障,部署多个实例提供服务,同时可以在VIP做负载均衡。
通过 iostat ,我们可以得到磁盘的 I/O 使用率、吞吐量、响应时间以及 IOPS 等性能指标;而通过 pidstat ,则可以观察到进程的 I/O 吞吐量以及块设备 I/O 的延迟等。
进程想要访问磁盘,就必须使用系统调用。strace 是最常用的跟踪进程系统调用的工具,但是无法分析僵尸进程的情况。读写文件必须通过系统调用完成。观察系统调用情况,就可以知道进程正在写的文件。strace 正是分析系统调用时最常用的工具。
给pidstat加上 -d 参数,可以实时查看每个进程的 I/O 情况
给pidstat加上 -w 选项,可以查看每个进程上下文切换的情况
pidstat 默认显示进程的指标数据,加上 -t 参数后,才会输出线程的指标。
iotop可以按照 I/O 大小对进程排序,然后找到 I/O 较大的那些进程
lsof 专门用来查看进程打开文件列表,这里的“文件”不只有普通文件,还包括了目录、块设备、动态库、网络套接字等。
如果文件系统中存储过多的小文件,就可能碰到索引节点容量已满的问题。
在数据库、大量小文件等这类随机读写比较多的场景中,IOPS 更能反映系统的整体性能;而在多媒体等顺序读写较多的场景中,吞吐量才更能反映系统的整体性能。
实时将相应的日志输出到 ELFK 中,是很多企业对日志处理的常用方法。这样不仅可以实现对日志的灵活查找,也可以实现对日志的长时间存储,并且也可以做更多的后续处理,生成可视化图形之类的。
watch 命令,可以定期运行一个命令来查看输出;再加上 -d 参数,还可以高亮出变化的部分
watch -d cat /proc/softirqs
Buffer 是对磁盘数据的缓存,而 Cache 是文件数据的缓存,它们既会用在读请求中,也会用在写请求中。
直接IO是跳过Buffer,裸IO是跳过文件系统(还是有buffer的)
当 OOM 发生时,系统会把相关的 OOM 信息,记录到日志中。可以在终端中执行 dmesg 命令,查看系统日志,并定位 OOM 相关的日志
内核线程的名称(CMD)都在中括号里,ps -ef | grep "\[.*\]" --查看内核线程
普通进程用strace、pstack、lsof工具分析,内核进程用perf分析。
一个完整的监控系统通常由数据采集、数据存储、数据查询和处理、告警以及可视化展示等多个模块组成。
对于跟踪的内容,主要判断的是:消耗时间的方法是不是固定的。如果时间不是消耗在了固定的方法上,那就有些麻烦了,因为这说明不是方法本身的问题,而是其他的资源影响了方法的执行时间;如果时间一直消耗在了固定的方法上,就比较容易了,只要接着去跟踪这个方法就好了。
不管是什么语言的应用,在性能分析的过程中,都是分析两个方法。执行速度够不够快。只有够快才能满足更高的 TPS。执行过程中内存用得多不多。内存用得少,才可以同时支持更多的请求。