以前组内一位大佬分享了一些关于系统性能优化方面的干货,这里我将它整理成文而且加入本身平时经常使用的一些工具和技巧。因为关于系统性能优化涉及的内容很是多,我会分几篇文章来分享。此次分享下定位系统层面问题
的经常使用方法。java
异步化能够提升系统的吞吐量的灵活性,可是不会得到更快的响应时间。
-i:指定须要的网
-s:抓取数据包时默认抓取长度为68字节,加上-s 0后能够抓到完整的数据包
-w:监听的数据包写入指定的文件
复制代码
tcpdump -i eth1 host 10.1.1.1 // 抓取全部通过eth1,目的或源地址是10.1.1.1的网络数据包
tcpdump -i eth1 src host 10.1.1.1 // 源地址
tcpdump -i eth1 dst host 10.1.1.1 // 目的地址
复制代码
若是想使用wireshark分析tcpdump的包,须要加上是 -s 参数:linux
tcpdump -i eth0 tcp and port 80 -s 0 -w traffic.pcap
复制代码
tcpcopy是一种请求复制工具,用于实时和离线回放,它能够将线上流量拷贝到测试机器,实时模拟线上的真实环境,达到程序不上线的状况下承担线上真实流量的测试。实战演习的必备工具。ios
tcpdump -i eth0 -w online.pcap tcp and port 80
复制代码
tcpcopy -x 80-10.1.x.x:80 -i traffic.pcap
tcpcopy -x 80-10.1.x.x:80 -a 2 -i traffic.pcap // 离线回放加速2倍
复制代码
tcpcopy -x 80-10.1.x.x:80 -r 20 // 20%引流
tcpcopy -x 80-10.1.x.x:80 -n 3 // 放大三倍引流
复制代码
我的很是推荐wrk,轻量且压测结果准确,结合Lua脚本能够支持更复杂的测试场景。web
压测示例:4个线程来模拟1000个并发链接,整个测试持续30秒,链接超时30秒,打印出请求的延迟统计信息。性能优化
> wrk -t4 -c1000 -d30s -T30s --latency http://www.baidu.com
Running 30s test @ http://www.baidu.com
4 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 1.71s 3.19s 26.51s 89.38%
Req/Sec 15.83 10.59 60.00 66.32%
Latency Distribution
50% 434.52ms
75% 1.70s
90% 5.66s
99% 14.38s
1572 requests in 30.09s, 26.36MB read
Requests/sec: 52.24
Transfer/sec: 0.88MB
复制代码
更多参数帮助信息:bash
> wrk --help
Usage: wrk <options> <url>
Options:
-c, --connections <N> Connections to keep open
-d, --duration <T> Duration of test
-t, --threads <N> Number of threads to use
-s, --script <S> Load Lua script file
-H, --header <H> Add header to request
--latency Print latency statistics
--timeout <T> Socket/request timeout
-v, --version Print version details
Numeric arguments may include a SI unit (1k, 1M, 1G)
Time arguments may include a time unit (2s, 2m, 2h)
复制代码
能够从如下几个方面衡量系统的性能:服务器
应用层面的性能指标:网络
系统层面指标有Cpu、内存、磁盘、网路等,推荐用一个犀利的命令查询系统性能状况:并发
dstat -lcdngy
异步
dstat很是强大,能够实时的监控cpu、磁盘、网络、IO、内存等使用状况。
yum install -y dstat
-c:显示CPU系统占用,用户占用,空闲,等待,中断,软件中断等信息。
-C:当有多个CPU时候,此参数可按需分别显示cpu状态,例:-C 0,1 是显示cpu0和cpu1的信息。
-d:显示磁盘读写数据大小。 -D hda,total:include hda and total。
-n:显示网络状态。 -N eth1,total:有多块网卡时,指定要显示的网卡。
-l:显示系统负载状况。
-m:显示内存使用状况。
-g:显示页面使用状况。
-p:显示进程状态。
-s:显示交换分区使用状况。
-S:相似D/N。
-r:I/O请求状况。
-y:系统状态。
--ipc:显示ipc消息队列,信号等信息。
--socket:用来显示tcp udp端口状态。
-a:此为默认选项,等同于-cdngy。
-v:等同于 -pmgdsc -D total。
--output 文件:此选项也比较有用,能够把状态信息以csv的格式重定向到指定的文件中,以便往后查看。例:dstat --output /root/dstat.csv & 此时让程序默默的在后台运行并把结果输出到/root/dstat.csv文件中。
复制代码
使用率:Cpu是最重要的资源,若是CPU在等待,也会致使Cpu高使用率。
CPU利用率 = 1 - 程序占用cpu时间/程序总的运行时间
用户时间/内核时间:大体判断应用是计算密集型仍是IO密集型。
CPU花在用户态代码的时间称为用户时间,而执行内核态代码的时间称为内核时间。内核时间主要包括系统调用,内核线程和中断的时间。当在整个系统范围内进行测量时,用户时间和内核时间之比揭示了运行的负载类型。计算密集型应用会把大量时间花在用户态代码上,用户时间/内核时间之比接近99/1。这样的例子有图像处理,数据分析等。I/O密集型应用的系统调用频率较高,经过执行内核代码进行I/O操做。一个进行网络I/O的Web服务器的用户/内核时间比大约为70/30。
负载load:在特定时间间隔内运行队列中的平均进程数。每一个CPU都有一个运行队列,队列里存放着已经就绪,等待被CPU执行的线程。理想状态下,但愿负载平均值小于等于Cpu核数。
Cpu使用率和load的区别:
磁盘空间:没有空间会致使程序没法启动或者报错。
du -sh //查看当前文件夹下全部文件大小
df -hl //以磁盘分区为单位查看文件系统
复制代码
有时候linux服务器的系统日志文件过大致使磁盘使用率太高,推荐两种清理方式:
sudo /dev/null > /var/log/**.log //删除指定的较大日志文件,速度快
sudo find /var/log/ -type f -mtime +30 -exec rm -f {} \ //删除30天以前的日志文件
复制代码
磁盘权限:没有权限会致使程序没法启动或者报错。
ll /yourdir
复制代码
磁盘性能测试
dd if=/dev/zero of=output.file bs=10M count=1
复制代码
io吞吐、iowait
这里重点说下这两个因素,大量的磁盘读写以及太高的iowait每每意味着磁盘多是瓶颈。实际上iowait并不能反映磁盘成为性能瓶颈,它实际测量的是cpu的时间:
%iowait = (cpu idle time)/(all cpu time)
复制代码
因此惟必定位磁盘成为性能瓶颈的直接方法仍是看read/write时间
。下面咱们着重介绍下如何定位io问题。
a. 宏观肯定是不是io的问题:top命令,能够从Cpu这一行看出浪费在I/O Wait上的CPU百分比;数值越高表明越多的CPU资源在等待I/O权限。
b. 肯定具体磁盘问题:iostat
%util直观地反应可哪一块磁盘正在被写入,反应了设备的繁忙程度。每毫秒读写请求(rrqm/s wrqm/s)以及每秒读写(r/s w/s)对排查问题也提供了不少有用的信息。
c. 肯定具体进程:简单粗暴的iotop直观地反映了哪些进程是致使io问题的罪魁祸首。
d. ps判断进程是否等待IO同样强大
众所周知,ps命令为咱们提供了内存、cpu以及进程状态等信息,根据进程状态能够很容易查到正在等待IO的进程信息。
这里简单说下linux进程的几种状态:
其中等待I/O的进程状态通常是"uninterruptible sleep"即D状态,D状态以及R状态进程算为运行队列之中
,因此D状态进程过多也会致使系统load偏高,有兴趣能够看下linux load的计算原理。
查看D状态进程:
> for x in `seq 1 1 10`; do ps -eo state,pid,cmd | grep "^D"; echo "--------"; sleep 5; done
D 13389 /usr/libexec/gcc/x86_64-redhat-linux/4.4.7/cc1 -quiet -I../../include/cat -I../ -I. -dD message_sender.c -quiet -dumpbase message_sender.c -mtune=generic -auxbase message_sender -ggdb3 -O2 -O0 -o /tmp/ccivsNPE.s
复制代码
根据proc伪文件系统获取io相关信息:
> cat /proc/pid/io
rchar: 548875497
wchar: 270446556
syscr: 452342
syscw: 143986
read_bytes: 253100032
write_bytes: 24645632
cancelled_write_bytes: 3801088
复制代码
e. 肯定哪一个文件频繁读写:lsof -p pid
netstat -nt 查看tcp相关链接状态、链接数以及发送队列和接收队列
关于tcp的状态须要你们熟悉三次握手和四次挥手的过程,这里先列出tcp的所有状态。
客户端:SYN_SENT、FIN_WAIT一、FIN_WAIT二、CLOSING、TIME_WAIT
服务端:LISTEN、SYN_RCVD、CLOSE_WAIT、LAST_ACK
Common:ESTABLISHED、CLOSED
复制代码
Tcp状态变化图(摘自网络):
关于tcp状态的几点说明:
若是Recv-Q或者Send-Q持续有大量包存在,意味着链接存在瓶颈或者程序存在bug。
关于netstat还有不少有用的技巧,这里列出平时比较经常使用的:
netstat -nap | grep port 显示使用该端口的全部进程id
netstat -nat |awk '{print $6}'|sort|uniq -c|sort -rn 查询所有状态并排序
awk '{print $1}' access.log |sort|uniq -c|sort -nr|head -10 分析access.log获取访问作多的top n的ip地址
netstat -nat | grep "10.1.1.1:8080" |awk '{print $5}'|awk -F: '{print $1}'|sort|uniq -c|sort -nr|head -20 链接某服务器最多的top n的ip地址
netstat -s 若是重传的包持续增长,那么很大可能网卡存在问题
复制代码
ps -ef | grep java
sudo -u nobody jstack <pid> > /tmp/jstack.<pid>
复制代码
小技巧:jstack信息是某个时刻的堆栈信息,有时间仅仅一个jstack并不能分析出问题所在,能够适当多几回jstack,而后进行对比分析。
nid=native thread id,特殊的是nid使用十六进制标识,本地线程id是十进制标识,因此经过进制换算就能够讲二者对应起来。
16进制和10进制的互换:
printf %d 0x1b40
printf "0x%x" 6976
复制代码
a. 找出对应的java进程pid:
ps -ef | grep java
复制代码
b. 找出java进程中最消耗cpu的线程:
top -H -p <pid>
复制代码
说明:线程堆栈中能够看出对应线程执行的是Java代码仍是Native method
找不到对应的线程堆栈?
jstat -gccause用于查看垃圾收集的统计信息,如有发生垃圾回收,还会显示最后一次以及当前发生垃圾回收的缘由,它比-gcutil会多出最后一次垃圾回收的缘由以及当前正在发生的垃圾回收的缘由。
jstat -gccause pid 1234
复制代码
转载请注明出处,欢迎关注个人公众号:亚普的技术轮子