【发布时间】:2021-11-22 21:11:15
【问题描述】:
Windows 服务有多个永久 TCP 连接,接受数据,在单独的线程中处理它,定期向所有连接的客户端发送更新。处理必须尽可能实时完成,客户端每 2-4 秒发送一条消息。
当使用 1900 个连接时,服务大约有 1970 个线程。到现在还好。但是当线程总数超过 2000-2200 时,事情就变得奇怪了——有时处理线程会无缘无故地阻塞 10 秒,即使使用实时优先级也是如此。在 10 秒内,传入队列会填满数千个请求,因此即使是一秒钟的延迟也是不可接受的。尝试使用 TSchedulerOfThread 来限制线程数,但实际上这只限制了连接数...
我知道 Indy 每个 TCP 连接消耗一个线程。所以我测试了使用 Windows 消息传递的 Overbyte ICS(不完全是这个的粉丝,但没有真正的选择)。线程数显着降低(仍然是 70,但没关系),在 3000 个连接时也能正常工作。几个小时后,服务在没有调用堆栈的情况下随机崩溃(正在使用 madExcept)。 Windows 事件日志中只有一条记录标记为“应用程序崩溃”。
因此,Indy 或 ICS 都不适合我。
中间有什么解决办法吗?我可以负担得起使用 1000 个线程,但不是 3000...
【问题讨论】:
-
您的应用是 32 位还是 64 位?因为在 32 位上,2000 个线程将消耗几乎全部可用内存,仅用于堆栈的 32 位进程。
-
对不起,忘了说。它是 64 位的。
-
AFAIK 对每个进程的线程数没有任何硬性限制,尤其是在 64 位上。因此,您在系统上看到的性能影响很可能是基于其他系统资源的某些限制,可能是可用物理内存、内核数量或其他繁重的进程。
-
目前该服务在 Intel Xeon Gold 5218、64 核、128 GB 内存上运行。服务工作集是 230 MB,所以硬件应该不是问题。 CPU 的总体利用率低于 20%。奇怪的是,即使有 2200 个线程,它也可以完美运行几天而没有问题,或者每隔几个小时就会出现应用程序挂起。没找到规则...
-
2000 个消息“生产者”,只有一个“工作”线程用于繁重的工作,嗯,我认为拥有多个“工作”线程会更好更可靠,每个线程都会从其中获取消息排队并完成工作。在这种情况下,当某个工作线程由于某种原因冻结时,您的工作进程不会停止(除非该问题跨越所有“工作”线程)。
标签: multithreading delphi tcp