以前組內一位大佬分享了一些關於系統性能優化方面的乾貨,這裏我將它整理成文而且加入本身平時經常使用的一些工具和技巧。因爲關於系統性能優化涉及的內容很是多,我會分幾篇文章來分享。此次分享下定位系統層面問題
的經常使用方法。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
複製代碼
轉載請註明出處,歡迎關注個人公衆號:亞普的技術輪子