UDP负载测试:如何模拟许多UDP客户端?

时间:2011-02-15 08:45:51

标签: .net sockets network-programming udp load-testing

我正在开发一个工具来在UDP服务器上执行负载测试(使用在NT 6.x上运行的C#/。NET 4.0,尽管这不太相关)。服务器与数万个客户端进行通信,每个客户端之间的通信流量非常低且不经常。所有通信都遵循请求 - 回复模式,其中一方开始与另一方进行通信,然后另一方回复。当服务器需要向客户端发送内容时,他查找客户端的最后一个已知端点(IP +端口)并发送UDP数据包,并在单个已知端口上侦听回复,该端口用于接收来自所有端口的通信客户端。当客户端启动通信时,它已经知道服务器的端点,并且只是从临时端口发送数据包并等待同一端口上的回复。相同的短暂端口用于客户端的生命周期。

负载测试工具的设计非常简单;模仿每个客户的行为,状态和决策,以低而充足的复杂性。由于与每个客户端的通信只是偶然的(每隔几秒),并且每次通信所需的处理量非常小,我能想到的最佳方法是使用单个线程和单个套接字来执行所有通信对于大量模拟客户端,很可能仍然不会使线程完全忙并且套接字饱和。不幸的是,由于每个客户端从他自己的端口发送和接收这一事实,我遇到了两个问题:

  1. 套接字只允许从系统分配的临时端口或套接字绑定的特定端口发送UDP数据包。
  2. 套接字只接收来自绑定端口的UDP数据包。
  3. 每个客户一个套接字

    以上两个约束似乎意味着我必须为每个客户端创建一个套接字,因为UDP数据包必须来自某个端口,并且回复将被发送到该端口。所以第一个可能的解决方案就是这样做,为每个模拟客户端创建一个套接字。假设我们在一台机器上模拟30,000个客户端:

    1. 创建30,000个套接字甚至可行吗?这是最佳做法吗?它表现得好吗? Windows甚至会让你将30,000个套接字绑定到30,000个不同的端口吗?
    2. 如果服务器发送了任何数据,如何检查30,000个客户端套接字?我是否定期轮询所有套接字以查看是否收到了任何数据?有没有办法等待所有30,000个套接字并获得第一个到达其中任何一个的数据包?
    3. 操作系统为每个套接字分配了哪些资源?这些资源的限制是什么?达到这些资源的意义是什么?
    4. 所有客户的单个套接字

      另一种方法是使用单个套接字,但我之前提到的两个问题必须首先以某种方式解决:

      1. 将UDP数据包发送到Socket端口以外的端口的第一个问题是可解决的。它涉及创建一个原始套接字并自己构建UDP header,这意味着您可以指定任何您想要的源和目标端口。唯一的困难是计算可选但重要的UDP checksum,它不仅需要UDP头和有效负载,还需要源和目标IP地址,前者是有问题的,因为它需要调用Win32 API来获取({{ 3}}和GetBestInterface)涉及多个本机结构和大量非托管内存分配,从.NET角度来看可能存在可靠性缺陷,但可以做到。
      2. 使用单个套接字从列表(或范围)端口接收UDP数据包的第二个问题仍未得到解决。即使使用原始套接字,操作系统也要求我在允许我执行接收操作之前将套接字绑定到特定的单个端口。有没有办法做到这一点?总是存在数据包嗅探技术,但我宁愿避免它们,除非可以通过可靠且有点直接的方式从托管代码完成(在这种情况下,我愿意接受建议)。
      3. 其他方法?

        还有其他方法我没想过吗?我走错了路吗?你能想到更好的解决方案吗?我很乐意听到你的任何建议。

1 个答案:

答案 0 :(得分:4)

是的,您可以轻松创建> Windows机器上有30,000个套接字,但您可能需要调整MAXUSERPORT(请参阅here)。

使用I / O完成端口或异步I / O,然后您不必担心“轮询”并且可扩展性“正常”。

主要的资源问题是非页面缓冲池,但这在Vista或更高版本上已经不那么重要了(参见here),下一个问题是I / O锁定页面限制可能是个问题如果你为你的读取发布非常大的缓冲区,但鉴于这是UDP,我假设你将拥有'合理'大小的数据报,因此锁定的页面限制不太可能是一个问题。

我在这里写了一些关于可扩展性问题的博客:http://www.serverframework.com/asynchronousevents/2010/12/one-million-tcp-connections.html

我使用C++ socket server framework编写了类似于您尝试执行的工具。有一个UDP测试工具示例作为框架的一部分提供,它从唯一的客户端端口发送可配置数量的数据报并等待回复,并且易于调整以处理您的特定数据报格式和响应要求(请参阅{{3} })。