我们正在实现一个C#应用程序,它需要与遗留系统建立大量套接字连接。我们将(可能)使用第三方组件来完成有关终端仿真和数据抓取的繁重工作。我们今天拥有核心功能,现在我们需要扩展它。
在高峰时段,这可能是需要打开的数千个并发连接 - 也就是线程(甚至每年数万次)。这些连接主要处于闲置状态(除定期握手之外没有流量)几分钟(或几小时),直到遗留系统“触发我们关心的事件”,然后我们从此事件中抓取一些数据,执行一些工作流程,然后等待下一个活动。池中没有任何价值(据我们所知),因为线程很少需要重复使用。
我们正在寻找有助于有效使用这么多线程的任何好的模式或工具。在高端服务器硬件上运行不是问题,但如果可能的话,我们确实需要将应用程序限制在几台服务器上。
在我们的测试中,创建一个新线程,并初始化第三方控件似乎最初使用了大量CPU,但随后降至接近零。内存使用似乎约为800Megs / 1000个线程
有没有比创建和启动所需线程数更好/更有效的方法?
PS - 是的,我们知道创建这么多线程是不好的,但由于我们无法控制遗留应用程序,这似乎是我们唯一的选择。多个事件没有选项可以遇到单个套接字/连接。
感谢您的帮助或指示! 面包车
答案 0 :(得分:2)
你这样说:
汇集没有价值(到目前为止) 我们可以告诉)因为线程会 很少需要重复使用。
但是你这么说:
有什么更好/更多 高效而不仅仅是创造和 启动所需的线程数?
为什么会出现差异?您是否关心您创建的线程数量?线程池是处理大量空闲连接的正确方法。一些忙线程可以轻松处理许多空闲连接,并且所需资源更少。
答案 1 :(得分:1)
使用套接字的异步BeginReceive和BeginSend。它们将IO操作分派给操作系统并立即返回。
将委托和某些状态传递给IO操作完成时将调用的那些方法。
通常一旦完成处理IO,您就会立即再次调用BeginX。
Socket sock = GetSocket();
State state = new State() { Socket = sock, Buffer = new byte[1024], ThirdPartyControl = GetControl() };
sock.BeginReceive(state.Buffer, 0, state.Buffer.Length, 0, ProcessAsyncReceive, state);
void ProcessAsyncReceive(IAsyncResult iar)
{
State state = iar.AsyncState as State;
state.Socket.EndReceive(iar);
// Process the received data in state.Buffer here
state.ThirdPartyControl.ScrapeScreen(state.Buffer);
state.Socket.BeginReceive(state.buffer, 0, state.Buffer.Length, 0, ProcessAsyncReceive, iar.AsyncState);
}
public class State
{
public Socket Socket { get; set; }
public byte[] Buffer { get; set; }
public ThirdPartyControl { get; set; }
}
如果您接受传入连接,则以类似的方式使用BeginSend,以及BeginAccept。
低吞吐量操作异步通信可以轻松同时处理数千个客户端。
答案 2 :(得分:0)
答案 3 :(得分:0)
我建议使用Socket.Select()方法,并在单个线程中汇集多个套接字连接的处理。
例如,您可以为遗留系统的每50个连接创建一个线程。这些主线程将继续调用Socket.Select()等待数据到达。然后,这些主线程中的每一个都可以具有线程池,该线程池将具有数据的套接字传递给实际处理。处理完成后,线程可以传递回主线程。答案 4 :(得分:0)
使用Microsoft的协调和并发运行时的许多模式使得IO易于处理和轻松处理。它允许我们在我们正在开发的爬虫中每分钟抓取和处理超过6000个网页(可能会更高,但没有必要)。绝对值得投入时间投入到CCR的做事方式。这里有一篇很棒的文章: