一、用户级/系统最大文件句柄
文件句柄(File Handle):是 Linux 内核为进程打开的每个对象(文件、设备、socket 等)分配的唯一标识符(ID 编号)。它充当进程与内核之间的桥梁,用于内核快速寻址、进程间通信以及资源管理,是提升 Linux 系统 I/O 处理效率的关键机制。系统默认的 1024 限制在高并发场景下会出现 "Too many open files" 错误,导致即使系统内存资源充足,业务系统也会因无法建立新连接或打开必要文件而陷入卡死、拒绝服务的状态。
1、 默认限制与高并发瓶颈
Linux 系统为每个用户进程和整个系统都设置了文件句柄数量的上限。
- 用户级限制(ulimit -n):默认通常为 1024。这限制了单个进程能同时打开的文件描述符数量。
- 系统级限制(fs.file-max):定义了整个操作系统所有进程可打开的文件句柄总数。
在高并发场景(如 Web 服务器、数据库、消息中间件)中,一个进程可能需要同时处理成千上万的网络连接(每个连接至少占用一个文件句柄)。默认的 1024 限制会迅速被耗尽,导致进程抛出 "Too many open files" 错误。此时,即使服务器拥有充足的内存和 CPU 资源,业务系统也会因无法建立新连接或打开必要文件而陷入卡死、拒绝服务的状态。
2、用户级/系统级优化
2.1、用户级优化
(1)修改 /etc/security/limits.conf 或 /etc/security/limits.d/*.conf 文件。
(2)修改内容如下:
bash
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535
root soft nofile 65535
root hard nofile 65535
# 重新登录后执行
ulimit -n
# 应显示 65535
注:* 代表所有普通用户,nofile 是最大文件句柄数,nproc 为最大进程数,soft 和 hard 代表软硬限制,数值代表设置值。
在终端输入 ulimit -n 查看软限制(当前生效值),输入 ulimit -Hn 查看硬限制(最大值上限)。
2.2、系统级优化
(1)查看当前值:
bash
sysctl fs.file-max
cat /proc/sys/fs/file-max
(2)修改内容如下:
bash
fs.file-max = 655350 # 系统最大打开文件数,这个数应为单进程的2倍及以上,建议采用10倍。
kernel.pid_max = 65535 # 表示本机可以运行多少个进程,系统默认是32768,偏少。
fs.inotify.max_user_instances = 8192 # 单用户可创建 inotify 监控实例数
fs.inotify.max_user_watches = 524288 # 用户可以同时监控的文件数
sysctl -p # 生效配置
3、systemd 服务优化
关键点 :/etc/security/limits.conf 对 systemd 管理的服务不生效。
为特定服务设置(以 nginx 为例):
bash
# 创建服务配置覆盖目录
sudo mkdir -p /etc/systemd/system/nginx.service.d
# 创建配置文件
sudo vim /etc/systemd/system/nginx.service.d/limits.conf
# 添加以下内容
[Service]
LimitNOFILE=65535
# 重载并重启服务
sudo systemctl daemon-reload
sudo systemctl restart nginx
# 验证
cat /proc/$(pidof nginx | awk '{print $1}')/limits | grep "open files"
常见应用场景的推荐配置:
| 应用类型 | 建议 nofile 值 | 说明 |
|---|---|---|
| Nginx(高并发) | 100000 - 200000 | 处理大量静态文件/反向代理 |
| MySQL/PostgreSQL | 20000 - 50000 | 数据库连接数相关 |
| Java 应用(Tomcat) | 65535 - 100000 | 根据线程数调整 |
| Redis | 10000 - 20000 | 主要受连接数影响 |
| Docker 容器 | 1048576 | 容器内应用需要更大值 |
二、 网络高并发内核优化
网络传输层主要是 TCP、UDP 两种协议栈,现网 80% 业务采用 TCP。本文针对 TCP 进行内核优化。
(1)编辑 /etc/sysctl.conf 文件。
(2)填写如下内容到文件里面:
bash
net.ipv4.ip_local_port_range = 1024 65535 # 设置端口的可用范围
net.ipv4.tcp_tw_reuse = 1 # 允许新连接复用 TIME_WAIT 端口,避免出现端口耗尽问题
net.ipv4.tcp_tw_recycle = 0 # 关闭 TIME_WAIT 快速回收
net.ipv4.tcp_max_tw_buckets = 50000 # 防止 TIME_WAIT 占满服务器端口和内存
net.ipv4.tcp_syncookies = 1 # 开启防护 SYN 缓存防攻击
net.ipv4.ip_forward = 1 # 开启路由转发,在 Docker 场景、NAT 场景使用
三、内存内核优化
为了防止 OOM、脏页问题,需要对内存内核进行优化,提升内核响应速度。
(1)编辑 /etc/sysctl.conf 文件。
(2)填写如下内容到文件里面:
bash
vm.swappiness = 10 # 设置 SWAP 交换分区倾向,范围 0-100,本文设置为 10,尽量不使用交换内存。
vm.dirty_ratio = 20 # 数据写入内存,但是还没刷到硬盘。在脏页达到总内存 20% 时会强制刷入硬盘。
vm.dirty_background_ratio = 10 # 脏页达到总内存 10% 时主动刷入硬盘,不阻塞业务。
vm.dirty_expire_centisecs = 3000 # 脏页在内存中超过 30 秒进行落盘。
vm.dirty_writeback_centisecs = 500 # 每隔 5 秒进行脏页查询。
vm.overcommit_memory = 1 # 允许内存超分,数据库、Redis 场景应用,避免服务启动失败。
vm.overcommit_ratio = 80 # 物理内存给内核预留 20%,应用可用 80%。
vm.nr_hugepages = 2 # 设置大页内存,固定内存不被置换。数值以内存数据为准。
四、内核安全防控
提升内核层面安全,需要防范各类安全风险。最近的 Dirty Pipe 漏洞、copy_from_user 漏洞都可通过提权获取 root 权限。
(1)编辑 /etc/sysctl.conf 文件。
(2)填写如下内容到文件里面:
bash
kernel.kptr_restrict = 2 # 禁止内核暴露内存地址,防止提权利用。
# 禁止接收 ICMP 重定向报文,防止路由篡改
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
# 忽略广播 ARP、禁止 ARP 欺骗
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.icmp_echo_ignore_broadcasts = 1 # 禁止响应广播 ping,防止内网扫描、DDoS 放大攻击。
net.ipv4.icmp_ignore_bogus_error_responses = 1 # 忽略错误 ICMP 报文,防畸形包攻击。