Linux系统故障定位与优化
Posted John08
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux系统故障定位与优化相关的知识,希望对你有一定的参考价值。
内存查看
Ex1、内存使用紧张?
排查思路:
1) 用户访问量增加,导致服务使用内存增加;
2) 程序异常,内存泄漏;
使用vmstat查看内存使用
[root@inf-c7-n1 ~]# vmstat 1 10
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 15788388 2108 240736 0 0 0 0 5 4 0 0 100 0 0
0 0 0 15788388 2108 240736 0 0 0 0 37 23 0 0 100 0 0
0 0 0 15788388 2108 240736 0 0 0 0 43 30 0 0 100 0 0
0 0 0 15788388 2108 240736 0 0 0 0 29 27 0 0 100 0 0
0 0 0 15788388 2108 240736 0 0 0 0 29 19 0 0 100 0 0
0 0 0 15788388 2108 240736 0 0 0 0 31 24 0 0 100 0 0
0 0 0 15788388 2108 240736 0 0 0 0 19 13 0 0 100 0 0
0 0 0 15788388 2108 240736 0 0 0 0 45 39 0 0 100 0 0
0 0 0 15788248 2108 240736 0 0 0 2 55 51 0 0 100 0 0
0 0 0 15788248 2108 240736 0 0 0 0 23 20 0 0 100 0 0
显示说明:
字段 |
含义 |
procs |
进程信息字段: · -r:等待运行的进程数,数量越大,系统越繁忙。 · -b:不可被唤醒的进程数量,数量越大,系统越繁忙。 |
memory |
内存信息字段: · -swpd:虚拟内存的使用情况,单位为 KB。 · -free:空闲的内存容量,单位为 KB。 · -buff:缓冲的内存容量,单位为 KB。 · -cache:缓存的内存容量,单位为 KB。 |
swap |
交换分区信息字段: · -si:从磁盘中交换到内存中数据的数量,单位为 KB。 · -so:从内存中交换到磁盘中数据的数量,单位为 KB。 这两个数越大,表明数据需要经常在磁盘和内存之间进行交换,系统性能越差。 |
io |
磁盘读/写信息字段: · -bi:从块设备中读入的数据的总量,单位是块。 · -bo:写到块设备的数据的总量,单位是块。 这两个数越大,代表系统的 I/O 越繁忙。 |
system |
系统信息字段: · -in:每秒被中断的进程次数。 · -cs:每秒进行的事件切换次数。 这两个数越大,代表系统与接口设备的通信越繁忙。 |
cpu |
CPU信息字段: · -us:非内核进程消耗 CPU 运算时间的百分比。 · -sy:内核进程消耗 CPU 运算时间的百分比。 · -id:空闲 CPU 的百分比。 · -wa:等待 I/O 所消耗的 CPU 百分比。 · -st:被虚拟机所盗用的 CPU 百分比。 |
查看网络服务使用的内存
[root@localhost vmfs]# ss -tmpio
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 0 10.199.13.25:ssh 10.199.5.128:50143 users:(("sshd",pid=37674,fd=3)) timer:(keepalive,104min,0)
skmem:(r0,rb934516,t0,tb1000960,f8192,w0,o0,bl0,d0) sack cubic wscale:8,7 rto:227 rtt:26.317/18.779 ato:40 mss:1460 rcvmss:1460 advmss:1460 cwnd:10 ssthresh:16 bytes_acked:1257181613 bytes_received:5834836 segs_out:973509 segs_in:218250 send 4.4Mbps lastsnd:1 lastrcv:29 pacing_rate 8.9Mbps retrans:0/124 rcv_rtt:360 rcv_space:104368
ESTAB 0 0 [::1]:x11-ssh-offset [::1]:56476 users:(("sshd",pid=37674,fd=12))
skmem:(r0,rb1061184,t0,tb2626560,f0,w0,o0,bl0,d2) ts sack cubic wscale:7,7 rto:205 rtt:4.411/8.689 ato:40 mss:65464 rcvmss:536 advmss:65464 cwnd:10 bytes_acked:2248 bytes_received:484 segs_out:15 segs_in:19 send 1187.3Mbps lastsnd:15309980 lastrcv:15309980 lastack:15309980 pacing_rate 2374.5Mbps rcv_space:43690
ESTAB 0 0 [::1]:x11-ssh-offset [::1]:56472 users:(("sshd",pid=37674,fd=11))
skmem:(r0,rb6291456,t0,tb2626560,f0,w0,o0,bl0,d11) ts sack cubic wscale:7,7 rto:222 rtt:21.07/21.032 ato:40 mss:65464 rcvmss:25784 advmss:65464 cwnd:3 ssthresh:2 bytes_acked:2618904 bytes_received:1247927456 segs_out:68092 segs_in:110429 send 74.6Mbps lastsnd:2470 lastrcv:2476 lastack:2430 pacing_rate 149.1Mbps retrans:0/19 rcv_rtt:1229.38 rcv_space:1463216
使用 Memcheck 分析内存使用量
Memcheck 是默认的 valgrind 工具。它检测并报告大量难以检测和诊断到的内存错误,例如:
1) 不应发生的内存访问
2) 使用未定义或未初始化的值
3) 不正确的释放堆内存
4) 指示字重叠
5) 内存泄露
>>使用memcheck分析内存使用
[root@inf-c7-n1 media]# valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all echo hello
==7637== Memcheck, a memory error detector
==7637== Copyright (C) 2002-2017, and GNU GPL\'d, by Julian Seward et al.
==7637== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==7637== Command: echo hello
==7637==
hello
==7637==
==7637== HEAP SUMMARY:
==7637== in use at exit: 0 bytes in 0 blocks
==7637== total heap usage: 30 allocs, 30 frees, 3,681 bytes allocated
==7637==
==7637== All heap blocks were freed -- no leaks are possible
==7637==
==7637== For lists of detected and suppressed errors, rerun with: -s
==7637== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
>>使用cachegrind分析缓存
[root@inf-c7-n1 ~]# valgrind --tool=cachegrind echo hoo
==25512== Cachegrind, a cache and branch-prediction profiler
==25512== Copyright (C) 2002-2017, and GNU GPL\'d, by Nicholas Nethercote et al.
==25512== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==25512== Command: echo hoo
==25512==
hoo
==25512==
==25512== I refs: 202,301
==25512== I1 misses: 1,036
==25512== LLi misses: 1,029
==25512== I1 miss rate: 0.51%
==25512== LLi miss rate: 0.51%
==25512==
==25512== D refs: 70,674 (51,869 rd + 18,805 wr)
==25512== D1 misses: 3,312 ( 2,657 rd + 655 wr)
==25512== LLd misses: 2,677 ( 2,068 rd + 609 wr)
==25512== D1 miss rate: 4.7% ( 5.1% + 3.5% )
==25512== LLd miss rate: 3.8% ( 4.0% + 3.2% )
==25512==
==25512== LL refs: 4,348 ( 3,693 rd + 655 wr)
==25512== LL misses: 3,706 ( 3,097 rd + 609 wr)
==25512== LL miss rate: 1.4% ( 1.2% + 3.2% )
>>使用cg_annotate查看分析结果
[root@inf-c7-n1 ~]# cg_annotate cachegrind.out.25512
--------------------------------------------------------------------------------
I1 cache: 32768 B, 64 B, 8-way associative
D1 cache: 32768 B, 64 B, 8-way associative
LL cache: 2097152 B, 64 B, 8-way associative
Command: echo hoo
Data file: cachegrind.out.25512
Events recorded: Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw
Events shown: Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw
Event sort order: Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw
Thresholds: 0.1 100 100 100 100 100 100 100 100
Include dirs:
User annotated:
Auto-annotation: off
--------------------------------------------------------------------------------
Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw
--------------------------------------------------------------------------------
202,301 1,036 1,029 51,869 2,657 2,068 18,805 655 609 PROGRAM TOTALS
--------------------------------------------------------------------------------
Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw file:function
--------------------------------------------------------------------------------
56,525 12 12 13,788 1,034 859 16 3 0 ???:_dl_addr
27,862 14 14 9,106 215 138 4,363 12 9 ???:do_lookup_x
21,800 11 11 4,416 115 97 2,623 10 5 ???:_dl_lookup_symbol_x
19,501 47 47 5,298 696 643 2,296 254 243 ???:_dl_relocate_object
14,102 2 2 4,243 45 25 0 0 0 ???:strcmp
6,350 4 4 2,154 13 0 279 0 0 ???:getenv
5,700 5 5 2,362 54 20 680 6 4 ???:check_match.9525
5,655 6 6 1,084 65 62 490 42 42 ???:_nl_intern_locale_data
4,343 20 20 560 3 2 675 22 21 ???:_int_malloc
2,811 17 17 458 13 10 0 0 0 ???:__GI_strcmp
2,130 4 3 13 0 0 2,068 33 33 ???:memset
1,967 2 2 509 5 0 292 6 5 ???:_dl_name_match_p
1,733 46 46 380 19 19 183 25 25 ???:_dl_map_object_from_fd
1,354 4 4 177 7 5 0 0 0 ???:__GI_strlen
1,348 14 14 447 6 5 182 14 14 ???:_dl_check_map_versions
1,267 4 4 366 3 0 92 0 0 ???:malloc
1,169 6 6 438 44 11 104 0 0 ???:_dl_fixup
1,145 38 38 248 1 1 120 5 5 ???:_dl_map_object_deps
1,137 21 21 277 11 5 257 6 2 ???:_nl_load_locale_from_archive
1,080 8 8 156 6 1 252 0 0 ???:_nl_find_locale
1,049 74 74 215 27 20 135 16 16 ???:dl_main
1,037 14 14 258 13 13 76 4 4 ???:bcmp
904 2 2 164 0 0 118 1 1 ???:bsearch
>>使用massif查看程序使用堆栈
[root@inf-c7-n1 ~]# valgrind --tool=massif echo hello
==25380== Massif, a heap profiler
==25380== Copyright (C) 2003-2017, and GNU GPL\'d, by Nicholas Nethercote
==25380== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==25380== Command: echo hello
==25380==
hello
==25380==
[root@inf-c7-n1 ~]# ls
anaconda-ks.cfg massif.out.25380 MemoryLeak MemoryLeak.cpp test
>>使用ms_print查看分析结果
[root@inf-c7-n1 ~]# ms_print massif.out.25380
--------------------------------------------------------------------------------
Command: echo hello
Massif arguments: (none)
ms_print arguments: massif.out.25380
--------------------------------------------------------------------------------
KB
3.961^ @@@@@@@#
| :::@ #
| ::@::::@ #
| ::@::::@ #
| ::@::::@ #
| ::@::::@ #
| @:@::::@ #
| :@:@::::@ #
| :@:@::::@ #
| :@:@::::@ #
| ::@:@::::@ #
| ::@:@::::@ #
| ::@:@::::@ #
| ::@:@::::@ #
| ::@:@::::@ #
| ::@:@::::@ #
| :::@:@::::@ #
| :::@:@::::@ #
| :::@:@::::@ #
| :::@:@::::@ #
0 +----------------------------------------------------------------------->ki
0 153.1
Number of snapshots: 63
Detailed snapshots: [2, 12, 22, 32, 33 (peak), 43, 53]
--------------------------------------------------------------------------------
n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B)
--------------------------------------------------------------------------------
0 0 0 0 0 0
1 118,412 24 5 19 0
2 118,680 24 5 19 0
20.83% (5B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
->20.83% (5B) 0x4E60E04: _nl_normalize_codeset (in /usr/lib64/libc-2.17.so)
->20.83% (5B) 0x4E5B15E: _nl_load_locale_from_archive (in /usr/lib64/libc-2.17.so)
->20.83% (5B) 0x4E5A35D: _nl_find_locale (in /usr/lib64/libc-2.17.so)
->20.83% (5B) 0x4E59CC2: setlocale (in /usr/lib64/libc-2.17.so)
->20.83% (5B) 0x401428: ??? (in /usr/bin/echo)
->20.83% (5B) 0x4E4F554: (below main) (in /usr/lib64/libc-2.17.so)
--------------------------------------------------------------------------------
n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B)
--------------------------------------------------------------------------------
3 118,680 0 0 0 0
4 119,175 136 120 16 0
5 119,234 160 132 28 0
6 119,348 952 908 44 0
7 120,812 1,072 1,020 52 0
8 121,016 2,040 1,972 68 0
9 122,870 2,272 2,188 84 0
10 123,269 2,712 2,620 92 0
11 124,085 2,832 2,724 108 0
12 124,273 2,936 2,812 124 0
95.78% (2,812B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
->91.28% (2,680B) 0x4E5A9BF: _nl_intern_locale_data (in /usr/lib64/libc-2.17.so)
| ->91.28% (2,680B) 0x4E5B0A5: _nl_load_locale_from_archive (in /usr/lib64/libc-2.17.so)
| ->91.28% (2,680B) 0x4E5A35D: _nl_find_locale (in /usr/lib64/libc-2.17.so)
| ->91.28% (2,680B) 0x4E59CC2: setlocale (in /usr/lib64/libc-2.17.so)
| ->91.28% (2,680B) 0x401428: ??? (in /usr/bin/echo)
| ->91.28% (2,680B) 0x4E4F554: (below main) (in /usr/lib64/libc-2.17.so)
|
->04.09% (120B) 0x4E5B025: _nl_load_locale_from_archive (in /usr/lib64/libc-2.17.so)
| ->04.09% (120B) 0x4E5A35D: _nl_find_locale (in /usr/lib64/libc-2.17.so)
| ->04.09% (120B) 0x4E59CC2: setlocale (in /usr/lib64/libc-2.17.so)
| ->04.09% (120B) 0x401428: ??? (in /usr/bin/echo)
| ->04.09% (120B) 0x4E4F554: (below main) (in /usr/lib64/libc-2.17.so)
|
......
内存优化配置
配置HugeTLB Huge Page
>>查看当前hugepage大小,默认2MB,配置大页数量
[root@inf-c7-n1 ~]# cat /proc/sys/vm/nr_hugepages
0
[root@inf-c7-n1 ~]# cat /proc/meminfo |grep -i hugepage
AnonHugePages: 8192 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
[root@inf-c7-n1 sysctl.d]# sysctl -p 100-memctl.conf
vm.nr_hugepages = 10
[root@inf-c7-n1 sysctl.d]# cat /proc/meminfo |grep -i hugepage
AnonHugePages: 8192 kB
HugePages_Total: 10
HugePages_Free: 10
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
>>在内核启动参数中配置Hugepagesize
[root@inf-c7-n1 vm]# vim /etc/default/grub
[root@inf-c7-n1 vm]# cat /etc/default/grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed \'s, release .*$,,g\' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=c01/root rd.lvm.lv=c01/swap rhgb quiet default_hugepagesz=1G hugepagesz=1G"
GRUB_DISABLE_RECOVERY="true"
[root@inf-c7-n1 vm]# grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.10.0-862.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-862.el7.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-6fde1470ec6d473c8db4edb9e122c965
Found initrd image: /boot/initramfs-0-rescue-6fde1470ec6d473c8db4edb9e122c965.img
done
[root@inf-c7-n1 vm]#
[root@inf-c7-n1 vm]#
[root@inf-c7-n1 vm]# reboot
[root@inf-c7-n1 ~]# cat /proc/meminfo |grep -i hugepage
AnonHugePages: 8192 kB
HugePages_Total: 10
HugePages_Free: 10
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 1048576 kB
[root@inf-c7-n1 ~]# numastat -cm |egrep \'Node|Huge\'
Node 0 Total
AnonHugePages 8 8
HugePages_Total 10240 10240
HugePages_Free 10240 10240
HugePages_Surp 0 0
无numa结构按以上的配置即可,如下有numa结构的还需要配置脚本,开机服务来判断设定;
[root@localhost ~]# numastat -cm |egrep \'Node|Huge\'
Node 0 Node 1 Node 2 Node 3 Total
AnonHugePages 16380 8752 5726 12612 43470
HugePages_Total 0 0 0 0 0
HugePages_Free 0 0 0 0 0
HugePages_Surp 0 0 0 0 0
配置Transparent Hug Page
>>查看透明大页默认状态
[root@inf-c7-n1 ~]# cat /sys/kernel/mm/transparent_hugepage/enabled
[always] madvise never
always:全局开启
madvise:局部程序开启
never:禁用透明大页
>>查看透明大页内存整理
[root@inf-c7-n1 ~]# cat /sys/kernel/mm/transparent_hugepage/defrag
[always] madvise never
内存参数调优
路径:/proc/sys/vm
dirty_ratio:
触发pdflush将内存数据写入磁盘的阀值,默认20%;
dirty_bytes:
触发一个写入进程开始回写的脏存储器量,默认值为0;
dirty_background_ratio:
当脏页达到系统内存的10%时,强制回收写入磁盘,默认值10%;
dirty_background_bytes:
触发pdflush后台回写的脏存储器量,默认值为0;
dirty_expire_centisecs:
使用pdflush的脏存储器最小时间,默认值为3000;
dirty_writeback_centisecs:
pdflush活跃时间间隔(0为停用),默认值为500;
overcommit_memory
是否接受或拒绝大内存请求,默认值0;0超分;1不超分,2超分但不超过overcommit_ratio阀值;
overcommit_ratio
内存超分阀值,默认50%;
max_map_count
一个进程可使用的最大内存映射,默认值65530;
min_free_kbytes
预留内存空间大小,注意,这个参数不要随便设置,如果值太小,会影响系统的内存回收,可能导致系统hang住,或者触发oom-kill进程,如果太大(达到系统内存的5%-10%),容易导致内存溢出,或系统花费太长时间来回收内存。
oom_adj
当系统中panic_on_oom参数为0时,系统内存资源使用紧张时,oom_killer触发kill进程开始按照oom_score值的大小杀死进程(值越小越不容易被杀死)。Oom_adj的设置值会影响进程的oom_score,当值为-17禁用oom_killer杀死此进程,其他设置值范围为-16~15。
Swappiness
值的范围0~100,rhel7默认值30,控制系统使用匿名内存和页面内存的倾向,
值大:提高文件系统性能,同时将不太活跃的进程从内存中置换出来;
值小:避免进程从内存中置换出去,以牺牲I/O性能为代价来降低延迟;
Linux的进程使用的内存分为2种:
1) file-backed pages(有文件背景的页面,比如代码段、比如read/write方法读写的文件、比如mmap读写的文件,它们有对应的硬盘文件,因此如果要交换,可以直接和硬盘对应的文件进行交换;比如读取一个文件,没有关闭,也没有修改,交换时,就可以将这个文件直接放回硬盘,代码处理其实就是删除这部分内容,只保留一个索引,让系统知道这个文件还处于打开状态,只是它的内容不在内存,还在硬盘上),此部分页面叫做page cache;
2) anonymous pages(匿名页,如stack,heap,CoW后的数据段等;他们没有对应的硬盘文件,因此如果要交换,只能交换到swap分区),此部分页面,如果系统内存不充分,可以被swap到swapfile或者硬盘的swap分区。
因此,Linux在进行内存回收(memory reclaim)的时候,实际上可以从1类和2类这两种页面里面进行回收,而swappiness值就决定了回收这2类页面的优先级。swappiness越大,越倾向于回收匿名页;swappiness越小,越倾向于回收file-backed的页面。当然,它们的回收方法都是一样的LRU算法。(缓存淘汰算法--LRU算法LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是"如果数据最近被访问过,那么将来被访问的几率也更高"。新数据插入到链表头部;每当缓存命中(即缓存数据被访问),则将数据移到链表头部;当链表满的时候,将链表尾部的数据丢弃。)
vm.swappiness = 0
仅在内存不足的情况下--当剩余空闲内存低于vm.min_free_kbytes limit时,使用交换空间。
vm.swappiness = 1
内核版本3.5及以上、Red Hat内核版本2.6.32-303及以上,进行最少量的交换,而不禁用交换。
vm.swappiness = 10
当系统存在足够内存时,推荐设置为该值以提高性能。
如果swappiness=0,除非系统的内存过小(nr_free + nr_filebacked < high watermark)这种恶劣情况发生,都只是考虑交换file-backed的pages,就不会考虑交换匿名页了。
于是,现在的swappiness如果等于0的话,意味着哪怕匿名页占据的内存很大,哪怕swap分区还有很多的剩余空间,除非恶劣情况发生,都不会交换匿名页,因此这可能造成更大的OOM(Out Of Memory)压力。
红帽官方说明:
Warning
Setting swappiness==0 will very aggressively avoids swapping out, which increase the risk of OOM killing under strong memory and I/O pressure.
文件系统参数
路径:/proc/sys/fs
aio-max-nr
定义在异步输入/输出环境中允许的最大事件数量,默认值65536.
file-max
定义整个系统中最大的文件句柄,rhel7中默认最大值8192【或(mempages * (PAGE_SIZE / 1024)) / 10】.增加参数值可以解决由于缺少可用的文件句柄而引起的错误。
内核参数
路径:/proc/sys/kernel
msgmax
定义一个消息队列中单个消息最大值(KB),默认值65535,值不能超过队列大小(msgmnb)。
msgmnb
定义单个消息队列最大值(KB),默认65535.
msgmni
定义信息队列标识符的最大数量(以及队列的最大数量)。在 64 位架构的系统中,默认值为 1985。
shmall
定义系统中可使用的共享的页面数,在64位系统中,单个页面为4096bytes。
[root@rhel7 vm]# getconf PAGESIZE
4096
shmmax
定义页面上内核允许的单个共享内存片段的最大值(bytes)。
shmmni
定义系统范围内最大的共享内存片段数量。在所有系统中的默认值为4096。
threads-max
定义系统范围内内核能同时使用的最大线程量。默认值与内核参数max_threads 相同,【或mempages / (8 * THREAD_SIZE / PAGE SIZE )】,最小值为20.
以上是关于Linux系统故障定位与优化的主要内容,如果未能解决你的问题,请参考以下文章