服務(wù)異常的處理流程
查看服務(wù)的資源消耗
查看機器 cpu 的負(fù)載
top -b -n 1 |grep java|awk '{print
"VIRT:"$5,"RES:"$6,"cpu:"$9"%","mem:"$10"%"}'
查找 cpu 占用率高的線程
printf 0x%x 25842 jstack 25603 | grep 0x64f2
cat /proc/interrupts
(1)CPU
(2)Memory
(3)IO
(4)Network
可以從以下幾個方面監(jiān)控CPU的信息:
(1)中斷;
(2)上下文切換孤紧;
(3)可運行隊列豺裆;
(4)CPU 利用率。
系統(tǒng)內(nèi)存
這里的默認(rèn)顯示單位是kb号显。
各項指標(biāo)解釋
total:總計物理內(nèi)存的大小臭猜。
used:已使用多大。
free:可用有多少押蚤。
Shared:多個進程共享的內(nèi)存總額获讳。
buffers: 磁盤緩存的大小。
cache:磁盤緩存的大小活喊。
-/+ buffers/cached): used:已使用多大,free:可用有多少。
已用內(nèi)存 = 系統(tǒng)used memory - buffers - cached
(47000 = 3250000-201000-3002000)
可用內(nèi)存 = 系統(tǒng)free memory + buffers + cached
(3213000 = 10000+201000+3002000)
什么是buffer/cache钾菊?
buffer 指 Linux 內(nèi)存的:Buffer cache帅矗,緩沖區(qū)緩
cache 指 Linux內(nèi)存中的:Page cache,頁面緩存
page cache
page cache 主要用來作為文件系統(tǒng)上的文件數(shù)據(jù)的緩存來用煞烫,尤其是針對當(dāng)進程對文件有 read/write 操作的時候浑此。如果你仔細(xì)想想的話,作為可以映射文件到內(nèi)存的系統(tǒng)調(diào)用:mmap是不是很自然的也應(yīng)該用到 page cache滞详?在當(dāng)前的系統(tǒng)實現(xiàn)里凛俱,page cache 也被作為其它文件類型的緩存設(shè)備來用,所以事實上 page cache 也負(fù)責(zé)了大部分的塊設(shè)備文件的緩存工作料饥。
buffer cache
buffer cache 主要用來在系統(tǒng)對塊設(shè)備進行讀寫的時候蒲犬,對塊進行數(shù)據(jù)緩存的系統(tǒng)來使用。這意味著某些對塊的操作會使用 buffer cache 進行緩存岸啡,比如我們在格式化文件系統(tǒng)的時候原叮。一般情況下兩個緩存系統(tǒng)是一起配合使用的,比如當(dāng)我們對一個文件進行寫操作的時候巡蘸,page cache 的內(nèi)容會被改變奋隶,而 buffer cache 則可以用來將 page 標(biāo)記為不同的緩沖區(qū),并記錄是哪一個緩沖區(qū)被修改了悦荒。這樣唯欣,內(nèi)核在后續(xù)執(zhí)行臟數(shù)據(jù)的回寫(writeback)時,就不用將整個 page 寫回搬味,而只需要寫回修改的部分即可境氢。
在當(dāng)前的內(nèi)核中,page cache 是針對內(nèi)存頁的緩存身腻,說白了就是产还,如果有內(nèi)存是以page進行分配管理的,都可以使用page cache作為其緩存來管理使用嘀趟。
當(dāng)然脐区,不是所有的內(nèi)存都是以頁(page)進行管理的,也有很多是針對塊(block)進行管理的她按,這部分內(nèi)存使用如果要用到 cache 功能牛隅,則都集中到buffer cache中來使用。(從這個角度出發(fā)酌泰,是不是buffer cache改名叫做block cache更好媒佣?)然而,也不是所有塊(block)都有固定長度陵刹,系統(tǒng)上塊的長度主要是根據(jù)所使用的塊設(shè)備決定的默伍,而頁長度在X86上無論是32位還是64位都是4k。
系統(tǒng)如何回收cache?
Linux內(nèi)核會在內(nèi)存將要耗盡的時候也糊,觸發(fā)內(nèi)存回收的工作括堤,以便釋放出內(nèi)存給急需內(nèi)存的進程使用瓦灶。一般情況下徐矩,這個操作中主要的內(nèi)存釋放都來自于對buffer/cache的釋放烹玉。尤其是被使用更多的cache空間。既然它主要用來做緩存钞馁,只是在內(nèi)存夠用的時候加快進程對文件的讀寫速度虑省,那么在內(nèi)存壓力較大的情況下,當(dāng)然有必要清空釋放cache僧凰,作為free空間分給相關(guān)進程使用探颈。所以一般情況下,我們認(rèn)為buffer/cache空間可以被釋放允悦,這個理解是正確的膝擂。
但是這種清緩存的工作也并不是沒有成本。理解cache是干什么的就可以明白清緩存必須保證cache中的數(shù)據(jù)跟對應(yīng)文件中的數(shù)據(jù)一致隙弛,才能對cache進行釋放架馋。所以伴隨著cache清除的行為的,一般都是系統(tǒng)IO飆高全闷。因為內(nèi)核要對比cache中的數(shù)據(jù)和對應(yīng)硬盤文件上的數(shù)據(jù)是否一致叉寂,如果不一致需要寫回,之后才能回收总珠。
在系統(tǒng)中除了內(nèi)存將被耗盡的時候可以清緩存以外屏鳍,我們還可以人工觸發(fā)緩存清除的操作。
進程內(nèi)存
/proc/[pid]/status
通過/proc//status可以查看進程的內(nèi)存使用情況局服,包括虛擬內(nèi)存大械霾t。╒mSize),物理內(nèi)存大幸肌(VmRSS)山涡,數(shù)據(jù)段大小(VmData)唆迁,棧的大醒即浴(VmStk),代碼段的大刑圃稹(VmExe)鳞溉,共享庫的代碼段大小(VmLib)等等鼠哥。
cat /proc/[pid]/status
Name: gedit /*進程的程序名*/
State: S (sleeping) /*進程的狀態(tài)信息,具體參見http://blog.chinaunix.net/u2/73528/showart_1106510.html*/
Tgid: 9744 /*線程組號*/
Pid: 9744 /*進程pid*/
PPid: 7672 /*父進程的pid*/
TracerPid: 0 /*跟蹤進程的pid*/
VmPeak: 60184 kB /*進程地址空間的大小*/
VmSize: 60180 kB /*進程虛擬地址空間的大小reserved_vm:進程在預(yù)留或特殊的內(nèi)存間的物理頁*/
VmLck: 0 kB /*進程已經(jīng)鎖住的物理內(nèi)存的大小.鎖住的物理內(nèi)存不能交換到硬盤*/
VmHWM: 18020 kB /*文件內(nèi)存映射和匿名內(nèi)存映射的大小*/
VmRSS: 18020 kB /*應(yīng)用程序正在使用的物理內(nèi)存的大小熟菲,就是用ps命令的參數(shù)rss的值 (rss)*/
VmData: 12240 kB /*程序數(shù)據(jù)段的大锌凑(所占虛擬內(nèi)存的大小)抄罕,存放初始化了的數(shù)據(jù)*/
VmStk: 84 kB /*進程在用戶態(tài)的棧的大小*/
VmExe: 576 kB /*程序所擁有的可執(zhí)行虛擬內(nèi)存的大小,代碼段,不包括任務(wù)使用的庫 */
VmLib: 21072 kB /*被映像到任務(wù)的虛擬內(nèi)存空間的庫的大小*/
VmPTE: 56 kB /*該進程的所有頁表的大小*/
Threads: 1 /*共享使用該信號描述符的任務(wù)的個數(shù)*/
JVM 內(nèi)存分配
java內(nèi)存組成介紹:堆(Heap)和非堆(Non-heap)內(nèi)存
按照官方的說法:“Java 虛擬機具有一個堆帽衙,堆是運行時數(shù)據(jù)區(qū)域,所有類實例和數(shù)組的內(nèi)存均從此處分配贞绵。堆是在 Java 虛擬機啟動時創(chuàng)建的』衅”“在JVM中堆之外的內(nèi)存稱為非堆內(nèi)存(Non-heap memory)”榨崩。可以看出JVM主要管理兩種類型的內(nèi)存:堆和非堆章母。簡單來說堆就是Java代碼可及的內(nèi)存母蛛,是留給開發(fā)人員使用的;非堆就是JVM留給 自己用的乳怎,所以方法區(qū)彩郊、JVM內(nèi)部處理或優(yōu)化所需的內(nèi)存(如JIT編譯后的代碼緩存)、每個類結(jié)構(gòu)(如運行時常數(shù)池蚪缀、字段和方法數(shù)據(jù))以及方法和構(gòu)造方法 的代碼都在非堆內(nèi)存中秫逝。
JVM本身需要的內(nèi)存,包括其加載的第三方庫以及這些庫分配的內(nèi)存
NIO的DirectBuffer是分配的native memory
內(nèi)存映射文件询枚,包括JVM加載的一些JAR和第三方庫违帆,以及程序內(nèi)部用到的。上面 pmap 輸出的內(nèi)容里金蜀,有一些靜態(tài)文件所占用的大小不在Java的heap里刷后,因此作為一個Web服務(wù)器,趕緊把靜態(tài)文件從這個Web服務(wù)器中人移開吧渊抄,放到nginx或者CDN里去吧尝胆。
JIT, JVM會將Class編譯成native代碼护桦,這些內(nèi)存也不會少含衔,如果使用了Spring的AOP,CGLIB會生成更多的類嘶炭,JIT的內(nèi)存開銷也會隨之變大抱慌,而且Class本身JVM的GC會將其放到Perm Generation里去,很難被回收掉眨猎,面對這種情況抑进,應(yīng)該讓JVM使用ConcurrentMarkSweep GC,并啟用這個GC的相關(guān)參數(shù)允許將不使用的class從Perm Generation中移除睡陪, 參數(shù)配置: -XX:+UseConcMarkSweepGC -X:+CMSPermGenSweepingEnabled -X:+CMSClassUnloadingEnabled寺渗,如果不需要移除而Perm Generation空間不夠匿情,可以加大一點: -X:PermSize=256M -X:MaxPermSize=512M
JNI,一些JNI接口調(diào)用的native庫也會分配一些內(nèi)存信殊,如果遇到JNI庫的內(nèi)存泄露炬称,可以使用valgrind等內(nèi)存泄露工具來檢測
線程棧,每個線程都會有自己的椢芯校空間玲躯,如果線程一多,這個的開銷就很明顯了
jmap/jstack 采樣鳄乏,頻繁的采樣也會增加內(nèi)存占用跷车,如果你有服務(wù)器健康監(jiān)控,記得這個頻率別太高橱野,否則健康監(jiān)控變成致病監(jiān)控了朽缴。
1.方法區(qū)
也稱”永久代” 、“非堆”水援,它用于存儲虛擬機加載的類信息密强、常量、靜態(tài)變量蜗元、是各個線程共享的內(nèi)存區(qū)域或渤。默認(rèn)最小值為16MB,最大值為64MB许帐,可以通過-XX:PermSize 和 -XX:MaxPermSize 參數(shù)限制方法區(qū)的大小劳坑。
運行時常量池:是方法區(qū)的一部分,Class文件中除了有類的版本成畦、字段距芬、方法、接口等描述信息外循帐,還有一項信息是常量池框仔,用于存放編譯器生成的各種符號引用,這部分內(nèi)容將在類加載后放到方法區(qū)的運行時常量池中拄养。
2.虛擬機棧
描述的是java 方法執(zhí)行的內(nèi)存模型:每個方法被執(zhí)行的時候 都會創(chuàng)建一個“棧幀”用于存儲局部變量表(包括參數(shù))离斩、操作棧、方法出口等信息瘪匿。每個方法被調(diào)用到執(zhí)行完的過程跛梗,就對應(yīng)著一個棧幀在虛擬機棧中從入棧到出棧的過程。聲明周期與線程相同棋弥,是線程私有的核偿。
局部變量表存放了編譯器可知的各種基本數(shù)據(jù)類型(boolean、byte顽染、char漾岳、short轰绵、int、float尼荆、long左腔、double)、對象引用(引用指針捅儒,并非對象本身)液样,其中64位長度的long和double類型的數(shù)據(jù)會占用2個局部變量的空間,其余數(shù)據(jù)類型只占1個巧还。局部變量表所需的內(nèi)存空間在編譯期間完成分配蓄愁,當(dāng)進入一個方法時,這個方法需要在棧幀中分配多大的局部變量是完全確定的狞悲,在運行期間棧幀不會改變局部變量表的大小空間。
3.本地方法棧
與虛擬機椄窘铮基本類似摇锋,區(qū)別在于虛擬機棧為虛擬機執(zhí)行的java方法服務(wù),而本地方法棧則是為Native方法服務(wù)站超。
4.堆
也叫做java 堆荸恕、GC堆是java虛擬機所管理的內(nèi)存中最大的一塊內(nèi)存區(qū)域,也是被各個線程共享的內(nèi)存區(qū)域死相,在JVM啟動時創(chuàng)建融求。該內(nèi)存區(qū)域存放了對象實例及數(shù)組(所有new的對象)。其大小通過-Xms(最小值)和-Xmx(最大值)參數(shù)設(shè)置算撮,-Xms為JVM啟動時申請的最小內(nèi)存生宛,默認(rèn)為操作系統(tǒng)物理內(nèi)存的1/64但小于1G,-Xmx為JVM可申請的最大內(nèi)存肮柜,默認(rèn)為物理內(nèi)存的1/4但小于1G陷舅,默認(rèn)當(dāng)空余堆內(nèi)存小于40%時,JVM會增大Heap到-Xmx指定的大小审洞,可通過-XX:MinHeapFreeRation=來指定這個比列莱睁;當(dāng)空余堆內(nèi)存大于70%時,JVM會減小heap的大小到-Xms指定的大小芒澜,可通過XX:MaxHeapFreeRation=來指定這個比列仰剿,對于運行系統(tǒng),為避免在運行時頻繁調(diào)整Heap的大小痴晦,通常-Xms與-Xmx的值設(shè)成一樣南吮。
由于現(xiàn)在收集器都是采用分代收集算法,堆被劃分為新生代和老年代阅酪。新生代主要存儲新創(chuàng)建的對象和尚未進入老年代的對象旨袒。老年代存儲經(jīng)過多次新生代GC(Minor GC)任然存活的對象汁针。
5.程序計數(shù)器
是最小的一塊內(nèi)存區(qū)域,它的作用是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號指示器砚尽,在虛擬機的模型里施无,字節(jié)碼解釋器工作時就是通過改變這個計數(shù)器的值來選取下一條需要執(zhí)行的字節(jié)碼指令,分支必孤、循環(huán)猾骡、異常處理、線程恢復(fù)等基礎(chǔ)功能都需要依賴計數(shù)器完成敷搪。
直接內(nèi)存
直接內(nèi)存并不是虛擬機內(nèi)存的一部分兴想,也不是Java虛擬機規(guī)范中定義的內(nèi)存區(qū)域。jdk1.4中新加入的NIO赡勘,引入了通道與緩沖區(qū)的IO方式嫂便,它可以調(diào)用Native方法直接分配堆外內(nèi)存,這個堆外內(nèi)存就是本機內(nèi)存闸与,不會影響到堆內(nèi)存的大小毙替。
JVM 內(nèi)存分析
查看 JVM 堆內(nèi)存情況
jmap -heap [pid]
@server ~]$ jmap -heap 837
Attaching to process ID 837, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.71-b01
using thread-local object allocation.
Parallel GC with 4 thread(s)//GC 方式
Heap Configuration: //堆內(nèi)存初始化配置
MinHeapFreeRatio = 0 //對應(yīng)jvm啟動參數(shù)-XX:MinHeapFreeRatio設(shè)置JVM堆最小空閑比率(default 40)
MaxHeapFreeRatio = 100 //對應(yīng)jvm啟動參數(shù) -XX:MaxHeapFreeRatio設(shè)置JVM堆最大空閑比率(default 70)
MaxHeapSize = 2082471936 (1986.0MB) //對應(yīng)jvm啟動參數(shù)-XX:MaxHeapSize=設(shè)置JVM堆的最大大小
NewSize = 1310720 (1.25MB)//對應(yīng)jvm啟動參數(shù)-XX:NewSize=設(shè)置JVM堆的‘新生代’的默認(rèn)大小
MaxNewSize = 17592186044415 MB//對應(yīng)jvm啟動參數(shù)-XX:MaxNewSize=設(shè)置JVM堆的‘新生代’的最大大小
OldSize = 5439488 (5.1875MB)//對應(yīng)jvm啟動參數(shù)-XX:OldSize=<value>:設(shè)置JVM堆的‘老生代’的大小
NewRatio = 2 //對應(yīng)jvm啟動參數(shù)-XX:NewRatio=:‘新生代’和‘老生代’的大小比率
SurvivorRatio = 8 //對應(yīng)jvm啟動參數(shù)-XX:SurvivorRatio=設(shè)置年輕代中Eden區(qū)與Survivor區(qū)的大小比值
PermSize = 21757952 (20.75MB) //對應(yīng)jvm啟動參數(shù)-XX:PermSize=<value>:設(shè)置JVM堆的‘永生代’的初始大小
MaxPermSize = 85983232 (82.0MB)//對應(yīng)jvm啟動參數(shù)-XX:MaxPermSize=<value>:設(shè)置JVM堆的‘永生代’的最大大小
G1HeapRegionSize = 0 (0.0MB)
Heap Usage://堆內(nèi)存使用情況
PS Young Generation
Eden Space://Eden區(qū)內(nèi)存分布
capacity = 33030144 (31.5MB)//Eden區(qū)總?cè)萘? used = 1524040 (1.4534378051757812MB) //Eden區(qū)已使用
free = 31506104 (30.04656219482422MB) //Eden區(qū)剩余容量
4.614088270399305% used //Eden區(qū)使用比率
From Space: //其中一個Survivor區(qū)的內(nèi)存分布
capacity = 5242880 (5.0MB)
used = 0 (0.0MB)
free = 5242880 (5.0MB)
0.0% used
To Space: //另一個Survivor區(qū)的內(nèi)存分布
capacity = 5242880 (5.0MB)
used = 0 (0.0MB)
free = 5242880 (5.0MB)
0.0% used
PS Old Generation //當(dāng)前的Old區(qū)內(nèi)存分布
capacity = 86507520 (82.5MB)
used = 0 (0.0MB)
free = 86507520 (82.5MB)
0.0% used
PS Perm Generation//當(dāng)前的 “永生代” 內(nèi)存分布
capacity = 22020096 (21.0MB)
used = 2496528 (2.3808746337890625MB)
free = 19523568 (18.619125366210938MB)
11.337498256138392% used
670 interned Strings occupying 43720 bytes.
關(guān)于這里的幾個generation網(wǎng)上資料一大把就不細(xì)說了,這里算一下求和可以得知前者總共給Java環(huán)境分配了644M的內(nèi)存践樱,而ps輸出的VSZ和RSS分別是7.4G和2.9G厂画,這到底是怎么回事呢?
前面jmap輸出的內(nèi)容里拷邢,MaxHeapSize 是在命令行上配的袱院,-Xmx4096m,這個java程序可以用到的最大堆內(nèi)存瞭稼。
VSZ是指已分配的線性空間大小忽洛,這個大小通常并不等于程序?qū)嶋H用到的內(nèi)存大小,產(chǎn)生這個的可能性很多环肘,比如內(nèi)存映射脐瑰,共享的動態(tài)庫,或者向系統(tǒng)申請了更多的堆廷臼,都會擴展線性空間大小苍在,要查看一個進程有哪些內(nèi)存映射,可以使用 pmap 命令來查看:
pmap -x [pid]
[root@server ~]$ pmap -x 837
837: java
Address Kbytes RSS Dirty Mode Mapping
0000000040000000 36 4 0 r-x-- java
0000000040108000 8 8 8 rwx-- java
00000000418c9000 13676 13676 13676 rwx-- [ anon ]
00000006fae00000 83968 83968 83968 rwx-- [ anon ]
0000000700000000 527168 451636 451636 rwx-- [ anon ]
00000007202d0000 127040 0 0 ----- [ anon ]
...
...
00007f55ee124000 4 4 0 r-xs- az.png
00007fff017ff000 4 4 0 r-x-- [ anon ]
ffffffffff600000 4 0 0 r-x-- [ anon ]
---------------- ------ ------ ------
total kB 7796020 3037264 3023928
這里可以看到很多anon荠商,這些表示這塊內(nèi)存是由mmap分配的寂恬。
RSZ是Resident Set Size,常駐內(nèi)存大小莱没,即進程實際占用的物理內(nèi)存大小初肉, 在現(xiàn)在這個例子當(dāng)中,RSZ和實際堆內(nèi)存占用差了2.3G饰躲,這2.3G的內(nèi)存組成分別為:
查看 JVM 堆各個分區(qū)的內(nèi)存情況
jstat -gcutil [pid]
[root@server ~]$ jstat -gcutil 837 1000 20
S0 S1 E O P YGC YGCT FGC FGCT GCT
0.00 80.43 24.62 87.44 98.29 7101 119.652 40 19.719 139.371
0.00 80.43 33.14 87.44 98.29 7101 119.652 40 19.719 139.371
分析 JVM 堆內(nèi)存中的對象
查看存活的對象統(tǒng)計
jmap -histo:live [pid]
dump 內(nèi)存
jmap -dump:format=b,file=heapDump [pid]
然后用jhat命令可以參看
jhat -port 5000 heapDump
在瀏覽器中訪問:http://localhost:5000/ 查看詳細(xì)信息
服務(wù)指標(biāo)
響應(yīng)時間(RT)
響應(yīng)時間是指系統(tǒng)對請求作出響應(yīng)的時間牙咏。直觀上看臼隔,這個指標(biāo)與人對軟件性能的主觀感受是非常一致的,因為它完整地記錄了整個計算機系統(tǒng)處理請求的時間妄壶。由于一個系統(tǒng)通常會提供許多功能摔握,而不同功能的處理邏輯也千差萬別,因而不同功能的響應(yīng)時間也不盡相同丁寄,甚至同一功能在不同輸入數(shù)據(jù)的情況下響應(yīng)時間也不相同氨淌。所以,在討論一個系統(tǒng)的響應(yīng)時間時伊磺,人們通常是指該系統(tǒng)所有功能的平均時間或者所有功能的最大響應(yīng)時間盛正。當(dāng)然,往往也需要對每個或每組功能討論其平均響應(yīng)時間和最大響應(yīng)時間屑埋。
對于單機的沒有并發(fā)操作的應(yīng)用系統(tǒng)而言豪筝,人們普遍認(rèn)為響應(yīng)時間是一個合理且準(zhǔn)確的性能指標(biāo)。需要指出的是摘能,響應(yīng)時間的絕對值并不能直接反映軟件的性能的高低壤蚜,軟件性能的高低實際上取決于用戶對該響應(yīng)時間的接受程度。對于一個游戲軟件來說徊哑,響應(yīng)時間小于100毫秒應(yīng)該是不錯的,響應(yīng)時間在1秒左右可能屬于勉強可以接受聪富,如果響應(yīng)時間達到3秒就完全難以接受了莺丑。而對于編譯系統(tǒng)來說,完整編譯一個較大規(guī)模軟件的源代碼可能需要幾十分鐘甚至更長時間墩蔓,但這些響應(yīng)時間對于用戶來說都是可以接受的梢莽。
吞吐量(Throughput)
吞吐量是指系統(tǒng)在單位時間內(nèi)處理請求的數(shù)量。對于無并發(fā)的應(yīng)用系統(tǒng)而言奸披,吞吐量與響應(yīng)時間成嚴(yán)格的反比關(guān)系昏名,實際上此時吞吐量就是響應(yīng)時間的倒數(shù)。前面已經(jīng)說過阵面,對于單用戶的系統(tǒng)轻局,響應(yīng)時間(或者系統(tǒng)響應(yīng)時間和應(yīng)用延遲時間)可以很好地度量系統(tǒng)的性能,但對于并發(fā)系統(tǒng)样刷,通常需要用吞吐量作為性能指標(biāo)仑扑。
對于一個多用戶的系統(tǒng),如果只有一個用戶使用時系統(tǒng)的平均響應(yīng)時間是t置鼻,當(dāng)有你n個用戶使用時镇饮,每個用戶看到的響應(yīng)時間通常并不是n×t,而往往比n×t小很多(當(dāng)然箕母,在某些特殊情況下也可能比n×t大储藐,甚至大很多)俱济。這是因為處理每個請求需要用到很多資源,由于每個請求的處理過程中有許多不走難以并發(fā)執(zhí)行钙勃,這導(dǎo)致在具體的一個時間點蛛碌,所占資源往往并不多。也就是說在處理單個請求時肺缕,在每個時間點都可能有許多資源被閑置左医,當(dāng)處理多個請求時,如果資源配置合理同木,每個用戶看到的平均響應(yīng)時間并不隨用戶數(shù)的增加而線性增加浮梢。實際上,不同系統(tǒng)的平均響應(yīng)時間隨用戶數(shù)增加而增長的速度也不大相同彤路,這也是采用吞吐量來度量并發(fā)系統(tǒng)的性能的主要原因秕硝。一般而言,吞吐量是一個比較通用的指標(biāo)洲尊,兩個具有不同用戶數(shù)和用戶使用模式的系統(tǒng)远豺,如果其最大吞吐量基本一致,則可以判斷兩個系統(tǒng)的處理能力基本一致坞嘀。
并發(fā)用戶數(shù)
并發(fā)用戶數(shù)是指系統(tǒng)可以同時承載的正常使用系統(tǒng)功能的用戶的數(shù)量躯护。與吞吐量相比,并發(fā)用戶數(shù)是一個更直觀但也更籠統(tǒng)的性能指標(biāo)丽涩。實際上棺滞,并發(fā)用戶數(shù)是一個非常不準(zhǔn)確的指標(biāo),因為用戶不同的使用模式會導(dǎo)致不同用戶在單位時間發(fā)出不同數(shù)量的請求矢渊。一網(wǎng)站系統(tǒng)為例继准,假設(shè)用戶只有注冊后才能使用,但注冊用戶并不是每時每刻都在使用該網(wǎng)站矮男,因此具體一個時刻只有部分注冊用戶同時在線移必,在線用戶就在瀏覽網(wǎng)站時會花很多時間閱讀網(wǎng)站上的信息,因而具體一個時刻只有部分在線用戶同時向系統(tǒng)發(fā)出請求毡鉴。這樣崔泵,對于網(wǎng)站系統(tǒng)我們會有三個關(guān)于用戶數(shù)的統(tǒng)計數(shù)字:注冊用戶數(shù)、在線用戶數(shù)和同時發(fā)請求用戶數(shù)猪瞬。由于注冊用戶可能長時間不登陸網(wǎng)站管削,使用注冊用戶數(shù)作為性能指標(biāo)會造成很大的誤差。而在線用戶數(shù)和同事發(fā)請求用戶數(shù)都可以作為性能指標(biāo)撑螺。相比而言含思,以在線用戶作為性能指標(biāo)更直觀些,而以同時發(fā)請求用戶數(shù)作為性能指標(biāo)更準(zhǔn)確些。
QPS每秒查詢率(Query Per Second)
每秒查詢率QPS是對一個特定的查詢服務(wù)器在規(guī)定時間內(nèi)所處理流量多少的衡量標(biāo)準(zhǔn)含潘,在因特網(wǎng)上饲做,作為域名系統(tǒng)服務(wù)器的機器的性能經(jīng)常用每秒查詢率來衡量。對應(yīng)fetches/sec遏弱,即每秒的響應(yīng)請求數(shù)盆均,也即是最大吞吐能力。
從以上概念來看吞吐量和響應(yīng)時間是衡量系統(tǒng)性能的重要指標(biāo)漱逸,QPS雖然和吞吐量的計量單位不同泪姨,但應(yīng)該是成正比的,任何一個指標(biāo)都可以含量服務(wù)器的并行處理能力饰抒。當(dāng)然Throughput更關(guān)心數(shù)據(jù)量肮砾,QPS更關(guān)心處理筆數(shù)。
CPU利用率
CPU Load Average < CPU個數(shù) 核數(shù) 0.7
Context Switch Rate
就是Process(Thread)的切換袋坑,如果切換過多仗处,會讓CPU忙于切換,也會導(dǎo)致影響吞吐量枣宫∑攀模《高性能服務(wù)器架構(gòu) 》這篇文章的第2節(jié)就是說的是這個問題的。究竟多少算合適也颤?google了一大圈洋幻,沒有一個確切的解釋。Context Switch大體上由兩個部分組成:中斷和進程(包括線程)切換翅娶,一次中斷(Interrupt)會引起一次切換文留,進程(線程)的創(chuàng)建、激活之類的也會引起一次切換故觅。CS的值也和TPS(Transaction Per Second)相關(guān)的,假設(shè)每次調(diào)用會引起N次CS渠啊,那么就可以得出
Context Switch Rate = Interrupt Rate + TPS* N
CSR減掉IR输吏,就是進程/線程的切換,假如主進程收到請求交給線程處理替蛉,線程處理完畢歸還給主進程贯溅,這里就是2次切換。也可以用CSR躲查、IR它浅、TPS的值代入公式中,得出每次事物導(dǎo)致的切換數(shù)镣煮。因此姐霍,要降低CSR,就必須在每個TPS引起的切換上下功夫,只有N這個值降下去镊折,CSR就能降低胯府,理想情況下N=0,但是無論如何如果N >= 4恨胚,則要好好檢查檢查骂因。另外網(wǎng)上說的CSR<5000,我認(rèn)為標(biāo)準(zhǔn)不該如此單一赃泡。
這三個指標(biāo)在 LoadRunner 中可以監(jiān)控到寒波;另外,在 linux 中升熊,也可以用 vmstat 查看r(Load Arerage)俄烁,in(Interrupt)和cs(Context Switch)
工具
uptime
dmesg
top
查看進程活動狀態(tài)以及一些系統(tǒng)狀況
vmstat
查看系統(tǒng)狀態(tài)、硬件和系統(tǒng)信息等
iostat
查看CPU 負(fù)載僚碎,硬盤狀況
sar
綜合工具猴娩,查看系統(tǒng)狀況
mpstat
查看多處理器狀況
netstat
查看網(wǎng)絡(luò)狀況
iptraf
實時網(wǎng)絡(luò)狀況監(jiān)測
tcpdump
抓取網(wǎng)絡(luò)數(shù)據(jù)包,詳細(xì)分析
mpstat
查看多處理器狀況
tcptrace
數(shù)據(jù)包分析工具
netperf
網(wǎng)絡(luò)帶寬工具
dstat
綜合工具勺阐,綜合了 vmstat, iostat, ifstat, netstat 等多個信息
Reference
http://tmq.qq.com/2016/07/it-is-necessary-to-know-the-background-performance-test/
https://www.ibm.com/developerworks/java/library/j-nativememory-linux/
http://www.oracle.com/technetwork/java/javase/index-137495.html
http://www.hollischuang.com/archives/303