1.从系统的角度来优化,改进服务器
1.系统调制
2.服务器调试
3.压力测试
2.最大文件描述符
作为守护进程的服务器程序就应该总是关闭标准输入,标准输出和标准错误这3个文件描述符。
Linux 对应用程序能打开的最大文件描述符有两个层次的限制:
1.用户级限制
用户级限制指的是目标用户运行的所有进程总共能打开的文件描述符
用户级查看文件描述符方法:
ulimit -n
设置:
ulimit -SHn 1024 //临时的
永久生效:
/etc/security/limits.conf
* hard nofile max-file-number //硬限制
* soft nofile max-file-number // 软限制
2.系统级限制
系统级限制指的是所有用户总共能打开的文件描述符
系统级文件描述符限制:
sysctl -w fs.filepmax = max-file-number // 临时
//永久生效
/etc/sysctl.conf
fs.file-max = max-file-number
sysctl -p
3.调整内核参数
几乎所有的内核模块,包括内核核心模块和驱动程序,都在 /proc/sys 文件系统下提供了某些配置文件以
供用户调整模块的属性和行为。通常一个配置文件对应一个内核参数,文件名就是参数的妹子,文件的内容就是参数的值。
我们可以通过命令 sysctl -a 查看所有这些内核参数。
1./proc/sys/fs (与文件系统相关)
1./proc/sys/fs/file-max 系统级文件描述符限制 //临时修改
一般修改 /proc/sys/fs/file-max 之后,应用程序需要把 /proc/sys/fs/inode-max
设置为新的 /proc/sys/fs/file-max 值的 3~4 倍,否则可能导致 i 节点数不够用
2./proc/sys/fs/epoll/max_user_watches 一个用户能够往 epoll 内核事件表中注册的事件总量。
它是指该用户打开的所有 epoll 实例总共能监听的事件数目,而不是单个 epoll 实例能监听的事件数目。
往 epoll 内核事件表注册一个事件,在 32 位的系统上大概消耗 90 字节的内核空间,在 64 位上则消耗
160 字节的内核空间。所以,这个参数限制了 epoll 使用的内核内存总量。
2./proc/sys/net (内核网络模块参数)
其中 TCP/IP 协议相关的参数主要位于如下3个子目录 : core, ipv4, ipv6
1. /proc/sys/net/core/somaxconn 指定 listen 监听队列里,能够建立完整连接从而进入 ESTABLISHED 状态
的 socket 的最大数目。
2./proc/sys/net/ipv4/tcp_max_syn_backlog 指定 listen 监听队列里,能够转移至 ESTABLISHED 或者 SYS_RCVD
状态的 socket 最大数目
3./proc/sys/net/ipv4/tcp_rmem 包含3个值,分别指定一个 socket 的 TCP 读缓冲区的最小值,默认值和最大值。
4./proc/sys/net/ipv4/tcp_syncookies 指定是否打开 TCP 同步标签(syscookie)。
同步标签通过启动 cookie 来防止一个监听 socket 因不停的重复接收来自同一个地址的连接请求(同步报文段),
而导致 listen 监听队列的溢出(所谓的 SYN 风暴)
除了通过直接修改文件的方式来修改这些系统参数之外,我们也可以使用 sysctl 命令来修改它们。但这2种修改方式都是临时的。
永久的方式是在 /etc/sysctl.conf 文件中加入相应网络参数及其数值,并执行 sysctl -p 使之生效,就像修改系统最大文件描述符一样。
4.gdb 调试
1.gdb 调试多进程程序
如果一个进程通过 fork 系统调用创建子进程,gdb 会继续调试原来的进程,子进程则会正常运行。那么如何调试子进程呢?2种方式:
1.单独调试子进程
gdb
attach pid
b
c
bt
2.使用调试器选项 follow-fork-mode
gdb 调试器选项 follow-fork-mode 允许我们选择程序在执行 fork 系统调用后是继续调试父进程还是调试子进程。其用法如下:
set follow-fork-mode mode(可选 parent 和 child)
2.gdb 调试多线程
1.info threads // 显示当前可调试的所有线程。gdb 会为每个线程分配一个ID,我们可以根据这个 ID 来操作对应的线程。
* 表示当前被调试的线程
2.thread ID // 调试目标 ID 指定的线程
3.set scheduler-locking [off|on|step]
调试多线程程序时,默认除了被调试的线程在执行外,其他线程也在继续执行,但有的时候我们希望只让被调试的线程执行。这
可以通过这个命令实现。该命令设置 scheduler-locking 的值: off 表示不锁定任何线程,即所有线程都可以执行,这是默认值;
on 表示只有当前被调试的线程会继续执行; step 表示在单步执行的时候,只有当前线程会执行。
调试进程池或者线程池一个不错的方法:是先将池中的进程个数或者线程个数减少至1,以观察程序的逻辑是否正确;
然后逐步增加进程或者线程的数量,以调试进程或者线程的同步是否正确。
5.压力测试
16.1 最大文件描述符数
16.2 调整内核参数
16.3 gdb 调试
16.4 压力测试