我尝试用不同的语言(C#,Java,C ++,PHP)创建一个简单的程序来连接服务器,所有程序都以相同的方式运行。所以我认为这个问题更像是OS级别的事情。
基本上我希望程序使用TCP套接字连接到服务器并发送1个字节然后关闭套接字。这需要每秒进行数千次并持续一段时间。这是为了对服务器进行基准测试。
到目前为止,在几千个客户端套接字之后,系统完全停止了。它只能在冷却一分钟左右后开始创建插座。我确保在传输后关闭了每个插座。
现在,这类问题熟悉Apache这样的服务器,建议使用实用程序(如ab / siege)使用keep-alive协议对Apache进行基准测试。即,创建少量TCP连接但通过它们发出多个请求以用于基准测试。然而,在我们的情况下这是不可能的,因为我们的专有服务器不提供HTTP并且不支持HTTP 1.1 keep-alive模型。
那怎么能实现呢?我检查了以下限制
ulimit
设置为非常高的数字TCP TIME_WAIT
和/proc/sys/net/ipv4/tcp_rw_recycle
设置为1来消除/proc/sys/net/ipv4/tcp_rw_reuse
。(我确实已确认netstat
没有TIME_WAIT
套接字)PS。这是 NOT 服务器端限制。我们通过购买另一个盒子并在第一个客户端盒子拒绝制作新套接字时在其上运行相同的客户端代码来测试这个。服务器处理得很好。我们不想购买5-10个盒子并在它们之间旋转以克服这个问题。
操作系统:Fedora 10 Linux 2.6.24-23-xen#1 SMP
答案 0 :(得分:9)
医生回答说,“好吧,不要做那个!”
看,你正在做的是非常不自然的过程。建立TCP连接需要握手,发送超过每个消息一个字节的字节远。设置和拆卸时间将非常重要。您正在做的事情很可能是使用与该握手相关联的内核资源;果然,如果你随后让它单独停止拍打它,它最终会赶上来。
那么,你真正试图衡量的是什么?你真的想要做什么?如果你真的想一次发送一个字节 - 上帝禁止 - 至少考虑使用udp;没有可怕的设置/拆解。与开销相比,它仍然非常低效 - 即使UDP数据包需要20字节的帧 - 但它更好。
答案 1 :(得分:7)
看一下Richard Jones的文章A Million-user Comet Application with Mochiweb, Part 3。这是关于在Erlang中实现一个Comet应用程序,但是“将其提高到一百万”部分描述了他如何对他的服务器进行基准测试;它打开时声明“从一个主机创建一百万个TCP连接是非常重要的”。这应该会让你知道你在做什么。
答案 2 :(得分:5)
您是否尝试在套接字上设置标志SO_REUSEADDR?
答案 3 :(得分:2)
你有可能用完了端口吗?除非你愿意在循环中调用bind()来查找下一个空闲端口,否则你只能得到5000到1024个端口。
bind()和0 for port返回1024-5000范围内的空闲端口。带有指定端口的bind()获取该端口(如果可用)。
int bindnextport(int s, struct sockaddr sa)
{
static int nextport = 1025;
int lastport;
lastport = nextport;
do {
sa.sa_data[0] = nextport >> 8;
sa.sa_data[1] = nextport & 255;
if (!bind(s, &sa, sizeof(sa))
return 0;
++nextport;
if (nextport >= 65536) nextport = 1024;
} while (lastport != nextport);
return 1;
}
答案 4 :(得分:1)
连接然后发送1个字节不是任何东西的基准,除了TCP协议本身。正如查理·马丁上面所说,大部分时间都是浪费连接然后断开插座。
我理解你想要进行基准测试,但这真的很好地代表了你的应用程序的功能吗?你真的要设置连接只是为了发送1个字节吗?
答案 5 :(得分:1)