系統優化總結——系統層面

系統優化總結

以前組內一位大佬分享了一些關於系統性能優化方面的乾貨,這裏我將它整理成文而且加入本身平時經常使用的一些工具和技巧。因爲關於系統性能優化涉及的內容很是多,我會分幾篇文章來分享。此次分享下定位系統層面問題的經常使用方法。java

系統性能定義

  • Throughout 吞吐量 (系統每秒鐘能夠處理的請求數)
  • Latency 延遲 (系統處理一個請求的延遲)
  • Usage 資源利用率

吞吐量和延遲的關係

  • 吞吐量越高,延遲會越大。由於請求量過大,系統太繁忙,因此響應時間會下降。
  • 延遲越小,能支持的吞吐量會越高。由於延遲短說明處理速度快,就能夠處理更多的請求。
  • 異步化能夠提升系統的吞吐量的靈活性,可是不會得到更快的響應時間。

系統性能壓測的經常使用工具

tcpdump

1. 經常使用參數:

-i:指定須要的網
-s:抓取數據包時默認抓取長度爲68字節,加上-s 0後能夠抓到完整的數據包
-w:監聽的數據包寫入指定的文件
複製代碼

2. 示例

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——線上引流壓測

tcpcopy是一種請求複製工具,用於實時和離線回放,它能夠將線上流量拷貝到測試機器,實時模擬線上的真實環境,達到程序不上線的狀況下承擔線上真實流量的測試。實戰演習的必備工具。ios

a. tcpdump錄製pace文件

tcpdump -i eth0 -w online.pcap tcp and port 80
複製代碼

b. 流量回放

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倍
複製代碼

c. 引流模式

tcpcopy -x 80-10.1.x.x:80 -r 20  // 20%引流
	
tcpcopy -x 80-10.1.x.x:80 -n 3  // 放大三倍引流
複製代碼

wrk & ApacheBench & Jmeter & webbench

我的很是推薦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)
複製代碼

定位性能瓶頸

能夠從如下幾個方面衡量系統的性能:服務器

  • 應用層面
  • 系統層面
  • JVM層面
  • Profiler

應用層面

應用層面的性能指標:網絡

  • QPS
  • 響應時間,9五、99線等。
  • 成功率

系統層面

系統層面指標有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高使用率。

    CPU利用率 = 1 - 程序佔用cpu時間/程序總的運行時間

  • 用戶時間/內核時間:大體判斷應用是計算密集型仍是IO密集型。

    CPU花在用戶態代碼的時間稱爲用戶時間,而執行內核態代碼的時間稱爲內核時間。內核時間主要包括系統調用,內核線程和中斷的時間。當在整個系統範圍內進行測量時,用戶時間和內核時間之比揭示了運行的負載類型。計算密集型應用會把大量時間花在用戶態代碼上,用戶時間/內核時間之比接近99/1。這樣的例子有圖像處理,數據分析等。I/O密集型應用的系統調用頻率較高,經過執行內核代碼進行I/O操做。一個進行網絡I/O的Web服務器的用戶/內核時間比大約爲70/30。

  • 負載load:在特定時間間隔內運行隊列中的平均進程數。每一個CPU都有一個運行隊列,隊列裏存放着已經就緒,等待被CPU執行的線程。理想狀態下,但願負載平均值小於等於Cpu核數。

Cpu使用率和load的區別:

  • 負載均值用來估量CPU利用率的發展趨勢,而不是某一時刻的情況。
  • 負載均值包括全部CPU的需求,而不只僅是在測量時活躍的。

磁盤

磁盤空間:沒有空間會致使程序沒法啓動或者報錯。

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進程的幾種狀態:

  • R (TASK_RUNNING),可執行狀態。
  • S (TASK_INTERRUPTIBLE),可中斷的睡眠狀態。
  • D (TASK_UNINTERRUPTIBLE),不可中斷的睡眠狀態。
  • T (TASK_STOPPED or TASK_TRACED),暫停狀態或跟蹤狀態。
  • Z (TASK_DEAD – EXIT_ZOMBIE),退出狀態,進程成爲殭屍進程。
  • X (TASK_DEAD – EXIT_DEAD),退出狀態,進程即將被銷燬。

其中等待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

網絡

1. nestat

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狀態的幾點說明:

  • 正常的鏈接應該是ESTABLISHED狀態,若是存在大量的SYN_SENT的鏈接,則須要看下防火牆規則。
  • 若是Recv-Q或者Send-Q持續有大量包存在,意味着鏈接存在瓶頸或者程序存在bug。
2. 一些其餘經常使用技巧

關於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 若是重傳的包持續增長,那麼很大可能網卡存在問題
複製代碼

JVM

定位問題的殺手鐗——線程堆棧

1. 獲取線程堆棧的步驟:
ps -ef | grep java
sudo -u nobody jstack <pid> > /tmp/jstack.<pid>
複製代碼

小技巧:jstack信息是某個時刻的堆棧信息,有時間僅僅一個jstack並不能分析出問題所在,能夠適當多幾回jstack,而後進行對比分析。

2. 如何從線程堆棧中找到本地線程對應的id

nid=native thread id,特殊的是nid使用十六進制標識,本地線程id是十進制標識,因此經過進制換算就能夠講二者對應起來。

16進制和10進制的互換:

printf %d 0x1b40
printf "0x%x" 6976
複製代碼
3. Cpu消耗高的分析方法

a. 找出對應的java進程pid:

ps -ef | grep java
複製代碼

b. 找出java進程中最消耗cpu的線程:

top -H -p <pid>
複製代碼
  • 將找出的線程id轉換爲16進制
  • jstack獲取java的線程堆棧
  • 根據16進制的id從線程堆棧中找到相關的堆棧信息

說明:線程堆棧中能夠看出對應線程執行的是Java代碼仍是Native method

找不到對應的線程堆棧?

  • 執行的Native method是從新建立的線程。
  • 代碼bug,堆內存耗完,jvm不斷執行full gc。
  • jvm自身bug😂。

垃圾收集的統計信息——查看Gc緣由

jstat -gccause用於查看垃圾收集的統計信息,如有發生垃圾回收,還會顯示最後一次以及當前發生垃圾回收的緣由,它比-gcutil會多出最後一次垃圾回收的緣由以及當前正在發生的垃圾回收的緣由。

jstat -gccause pid 1234
複製代碼

轉載請註明出處,歡迎關注個人公衆號:亞普的技術輪子

亞普的技術輪子
相關文章
相關標籤/搜索