我有一个非常简单的程序,在5分钟内编写,打开一个服务器套接字并循环遍历请求,并将发送给它的字节打印到屏幕。
然后我尝试对可以使用的连接进行基准测试,以尝试找出我可以使用此程序支持多少并发用户。
在另一台机器上(它们之间的网络未饱和)我创建了一个简单的程序进入循环并连接到服务器机器并发送字节“hello world”。
当循环为1000-3000时,客户端将完成所有发送的请求。当循环超过5000时,在完成第一个X个请求后开始超时。为什么是这样?我确保在循环中关闭我的套接字。
你能在一段时间内创建这么多连接吗?
这个限制是否仅适用于同一台机器之间我不需要担心这个问题在5000多个请求都来自不同机器的生产中?
答案 0 :(得分:25)
有一个限制,是的。请参阅ulimit
。
此外,您还需要考虑TIMED_WAIT
州。 TCP套接字关闭后(默认情况下),端口在TIMED_WAIT
状态下保持占用 2分钟。该值是可调的。即使它们已关闭,这也会“让你脱离插座”。
运行netstat
以查看TIMED_WAIT
内容。
P.S。 TIMED_WAIT
的原因是处理套接字关闭后到达的数据包的情况。这可能发生,因为数据包被延迟或者另一方只是不知道套接字已经关闭。这允许操作系统以静默方式丢弃这些数据包,而不会“感染”另一个不相关的套接字连接。
答案 1 :(得分:8)
在寻找最高性能时,会遇到很多问题和潜在的瓶颈。运行一个简单的hello world测试并不一定能找到它们。
可能的限制包括:
/proc/sys/net
进行大量内核调优.. ulimit
top
查看您的CPU是否达到最大值答案 2 :(得分:2)
您的服务器是否是单线程的?如果是,您使用的是什么轮询/多路复用功能?
使用select()不会超出编译时设置的硬编码最大文件描述符限制,这是绝对的(通常为256或更多)。
poll()更好,但是你最终会遇到可扩展性问题,每次循环时都会有大量的FD重新填充集合。
epoll()应该可以达到你遇到的其他限制。
10k连接应该很容易实现。使用最近的(ish)2.6内核。
您使用了多少台客户端计算机?你确定没有达到客户端限制吗?
答案 3 :(得分:2)
快速回答是2 ^ 16个TCP端口,64K。
系统强制限制的问题是配置问题,已在之前的评论中提及过。
对TCP的内部影响不太清楚(对我而言)。每个端口都需要内存进行实例化,进入列表并需要网络缓冲区来传输数据。
鉴于64K TCP会话,端口实例的开销可能是32位内核的问题,但不是64位内核(这里很容易接受更正)。使用64K会话的查找过程会使某些事情变慢并且每个数据包都会到达计时器队列,这也可能会有问题。传输数据的存储理论上可以膨胀到窗口大小乘以端口(可能是8 GB)。
连接速度问题(如上所述)可能就是您所看到的。 TCP通常需要时间来做事。但是,它不是必需的。可以非常有效地完成TCP连接,交易和断开连接(检查TCP会话的创建和关闭方式)。
有些系统每秒传递数十吉比特,因此数据包级别缩放应该没问题。
有些机器有足够的物理内存,所以看起来还不错。
如果仔细配置,系统的性能应该没问题。
事情的服务器端应该以类似的方式扩展。
我会担心内存带宽等问题。
考虑一个实验,您可以登录本地主机10,000次。然后输入一个字符。通过用户空间的整个堆栈将参与每个角色。活动占用空间可能会超过数据高速缓存大小。运行大量内存会给VM系统带来压力。上下文切换的成本可能接近一秒!
答案 4 :(得分:1)
您可能想查看/etc/security/limits.conf
答案 5 :(得分:1)
是的,限制是由内核设置的;有关详细信息,请查看Stack Overflow上的此主题:Increasing the maximum number of tcp/ip connections in linux