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算法LRULeast 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系统故障定位与优化的主要内容,如果未能解决你的问题,请参考以下文章

linux系统故障分析与排查

Linux的系统故障分析与排查

linux系统优化

Linux系统故障分析与排查--日志分析

[转]理解Linux的性能

Linux设备驱动故障定位指引与实例