主要包括:
- 使用
tcpdump
抓包; - 使用 gdb 调试器;
- 使用压力测试工具,模拟现实世界中的高并发请求,测试服务器在高压状态下的稳定性。
最大文件描述符数
Linux 对应用进程能打开的最大文件描述符数量有两个层次的限制:用户级限制和系统级限制。
用户级限制指目标用户运行的所有进程总共能打开的文件描述符数;
系统级限制指所有用户总共能打开的文件描述符数。
查看用户级文件描述符数量限制:
ulimit -n
将用户级文件描述符数量限制设定为 2048
:
ulimit -SHn 2048
但这种设置是临时的,只在当前session中有效,为永久修改用户级文件描述符数限制,可在/etc/security/limits.conf
文件中加入以下两项:
* soft nofile 65535
* hard nofile 65535
然后重启系统或者注销并重新登录以应用这些更改。
注意:nofile
指的是每个用户进程可以打开的文件数。
调整内核参数
几乎所有内核模块,包括内核核心模块和驱动程序,都在/proc/sys
目录下提供了某些配置文件以供用户调整模块的属性和行为。通常一个配置文件对应一个内核参数,文件名就是参数的名字,文件内容就是参数的值。我们可通过命令sysctl -a
查看所有这些内核参数,我们只讨论其中与网络编程关系较为紧密的内核参数。
/proc/sys/fs
目录下的文件
/proc/sys/fs
目录下的内核参数都与文件系统相关,对服务器程序来说,有以下重要参数:
/proc/sys/fd/file-max
:系统级文件描述符数限制,修改它是临时性修改,与以上所述临时修改系统级文件描述符数的限制效果相同。一般修改完该文件后,需要把/proc/sys/fd/inode-max
设置为新/proc/sys/fd/file-max
值的3~4倍,否则可能导致i节点数不够用。/proc/sys/fd/epoll/max_user_watches
:一个用户能够往epoll内核事件表中注册的事件总量。它是某用户打开的所有epoll实例总共能监听的事件数目,而不是单个epoll实例能监听的事件数目。往epoll内核事件表中注册一个事件,在32位系统上大概消耗90字节的内核空间,在64位系统上则消耗160字节的内核空间。这个内核参数限制了epoll使用的内核内存总量。
/proc/sys/net
目录下的文件
内核中网络模块的相关参数都位于/proc/sys/net
目录下,其中和TCP/IP协议相关的参数主要位于以下3个子目录中:core、ipv4、ipv6,以下是和服务器性能相关的部分参数:
/proc/sys/net/core/somaxconn
:指定listen
函数监听队列里,能建立完整连接从而进入ESTABLISHED
状态的socket的最大数目。/proc/sys/net/ipv4/tcp_max_syn_backlog
:指定listen
函数监听队列里,能够转移至ESTABLISHED
或SYN_RCVD
状态的socket的最大数目。/proc/sys/net/ipv4/tcp_wmem
:它包含3个值,分别指定一个socket的TCP写缓冲区的最小值、默认值、最大值。/proc/sys/net/ipv4/tcp_rmem
:它包含3个值,分别指定一个socket的TCP读缓冲区的最小值、默认值、最大值。/proc/sys/net/ipv4/tcp_syncookies
:指定是否打开TCP同步标签(syncookie),同步标签通过启动cookie来防止一个监听socket因不停地重复接收来自同一个地址的连接请求(同步报文段),而导致listen
函数监听队列溢出(所谓的SYN风暴)。
除了通过直接修改文件的方式来修改这些系统参数外,我们也可使用sysctl
命令来修改它们,这两种修改方式都是临时的,永久的修改方法是在/etc/sysctl.conf
文件中加入相应网络参数及其数值,并执行sysctl -p
使之生效。
gdb 调试
以下讨论如何使用gdb来调试多进程和多线程程序:
GDB(GNU Debugger)是一个强大的调试工具,主要用于调试C、C++和Fortran等编程语言的程序。它允许开发者执行程序的逐步执行、设置断点、检查变量值、修改内存内容等,从而帮助定位和修复程序中的错误。
用 gdb 调试多进程程序
如果一个进程通过fork
系统调用创建了子进程,gdb会继续调试原来的进程,子进程则正常运行,以下方式可调试子进程:
- 单独调试子进程:子进程本质上来说也是一个进程,因此我们可通过通用的 gdb 调试方法来调试它,例如,我们可先运行服务器,然后找到子进程的 PID,再将其附加(
attach
)到gdb调试器上; - 使用调试器选项follow-fork-mode:gdb 调试器的选项follow-fork-mode 允许我们选择程序在执行
fork
系统调用后是继续调试父进程还是调试子进程,其用法如下:
(gdb) set follow-fork-mode mode
mode
的可选值是parent
和child
,分别表示调试父进程和子进程
用 gdb 调试多线程程序
gdb 有一组命令可辅助多线程程序的调试
一个关于调试进程池和线程池程序的不错的方法是,将池中的进程或线程个数减少至1,以观察程序的逻辑是否正确,然后逐步增加进程或线程数量,以调试进程或线程的同步是否正确。
压力测试
压力测试程序有很多种实现方式,如 I/O 复用方式、多线程(进程)并发编程方式,以及这些方式的结合使用,但单纯的 I/O 复用方式的施压程度是最高的,因为线程和进程的调度本身也要占用一定CPU时间。