问题:ab -c 10000 报错 “too many open files”
在使用 Apache Benchmark (ab) 进行高并发负载测试时,当设置较高的并发连接数(如 -c 10000
)时,经常会遇到以下错误:
too many open files
这是因为操作系统对单个进程可以同时打开的文件描述符数量有默认限制。在 Linux 系统中,每个 TCP 连接都会消耗一个文件描述符,所以高并发测试很容易达到这个限制。
解决方案:增加文件描述符限制
临时解决方案
使用 ulimit
命令可以临时增加当前会话的文件描述符限制:
ulimit -n 65535
执行此命令后,再运行 ab 测试:
ab -n 100000 -c 10000 http://your-target-url/
永久解决方案
- 编辑
/etc/security/limits.conf
文件:
sudo vim /etc/security/limits.conf
- 添加以下行:
* soft nofile 65535
* hard nofile 65535
- 重新登录或重启系统使配置生效
突破单网卡 65535 端口限制
当尝试进行更大规模的并发测试(如 -c 100000
)时,即使解决了文件描述符的限制,还会面临另一个瓶颈:单个网卡的端口数量限制。
TCP/IP 协议中,一个 TCP 连接由四元组唯一标识:源 IP、源端口、目标 IP、目标端口。由于源端口范围通常是 1024-65535,这意味着从单一 IP 地址到单一目标 IP:端口的连接最多只能有约 64,000 个。
突破端口限制的方法
-
使用虚拟 IP
为测试机器配置多个虚拟 IP 地址,可以成倍增加可用的源 IP 地址:
# 添加虚拟 IP sudo ip addr add 192.168.1.101/24 dev eth0 sudo ip addr add 192.168.1.102/24 dev eth0 # 可以继续添加更多...
-
使用多网卡
如果测试机器有多个物理网卡,可以在不同网卡上配置 IP 地址,实现更多并发连接。
-
使用多台测试机器
分布式负载测试:使用多台机器同时向目标服务器发起请求。
替代工具:Locust
当面临 Apache Benchmark 的限制时,可以考虑使用更现代、更灵活的负载测试工具,如 Locust。
Locust 的优势:
- 分布式架构:支持多机器分布式测试,轻松突破单机限制
- 基于 Python:使用 Python 编写测试脚本,更灵活
- 实时 Web UI:提供实时监控和测试控制
- 支持复杂场景:可以模拟真实用户行为,不限于简单的 HTTP 请求
- 资源消耗更低:使用协程而非线程,可以用更少的资源创建更多虚拟用户
Locust 简单示例
from locust import HttpUser, task, between
class WebsiteUser(HttpUser):
wait_time = between(1, 5)
@task
def index_page(self):
self.client.get("/")
@task(3)
def view_item(self):
item_id = random.randint(1, 10000)
self.client.get(f"/item/{item_id}")
高并发测试的最佳实践
- 监控测试机器资源:确保 CPU、内存、网络不是瓶颈
-
调整内核参数:除了文件描述符,还需调整其他系统参数
# 编辑 /etc/sysctl.conf net.ipv4.ip_local_port_range = 1024 65535 net.ipv4.tcp_fin_timeout = 30 net.core.somaxconn = 65535 net.core.netdev_max_backlog = 65535
-
考虑测试的真实意义:超高并发测试应该关注系统在极限情况下的行为,而不仅仅是数字
- 渐进式测试:从低并发开始,逐步增加,观察系统响应变化
结论
Apache Benchmark 是一个简单易用的负载测试工具,但在高并发场景下会遇到文件描述符和端口数量的限制。通过调整系统参数、使用虚拟 IP 或多网卡,可以在一定程度上突破这些限制。对于更大规模或更复杂的负载测试场景,考虑使用 Locust 等更现代的分布式负载测试工具。
无论使用哪种工具,记住负载测试的目的是发现并解决性能瓶颈,而不仅仅是追求高并发数字。