Indy 服务器 — Windows IOCP(2 / 3)

· 功能

sgcWebSockets 2022.9.0 起,Indy 服务器 IOCP IOHandler 已从头重写,性能得到提升。IOCP IOHandler 仅在 sgcWebSockets Enterprise 包中提供。

使用 IOCP 可以避免"每客户端一线程"问题——随着服务器处理的连接数增加,性能会大幅下降。IOCP 使用少量线程处理多个客户端,这些线程在没有内容需要处理时会挂起,不消耗 CPU 周期。

配置

要为 Indy 服务器启用 IOCP,请前往 IOHandlerOptions 属性,将 IOHandler 类型选择为 iohIOCP

Server.IOHandlerOptions.IOHandlerType := iohIOCP;
Server.IOHandlerOptions.IOCP.IOCPThreads := 0; // the number of IOCP threads will be calculated automatically using the number of processors.
Server.IOHandlerOptions.IOCP.WorkOpThreads := 0; 

1. IOCPThreads:用于 IOCP 异步请求(重叠操作)的线程数,默认值为零,表示线程数量将根据处理器数量自动计算(Delphi 7 和 2007 除外,这两个版本固定为 32 个线程,因为不支持 cpucount 函数)。

2. WorkOpThreads:仅当您希望连接始终在同一线程中处理时才需要启用。使用 IOCP 时,请求由线程池处理,同一连接的每个请求可能由不同线程处理。如果您希望每个连接始终由同一线程处理,请在 WorkOpThreads 中设置用于处理这些请求的线程数量。这会影响服务器性能,仅建议在确实需要此功能时将该值设置为大于零。

当需要处理数千个连接时,建议为 Windows 服务器启用 IOCP;若服务器最多仅处理 100 个并发连接,则可以保持默认的 Indy 线程模型。

性能测试

以下简单测试展示了 Indy 线程模型与 IOCP 之间的差异。测试通过 WebSocket 协议连接到服务器,下表展示了 CPU 使用率和内存消耗情况。CPU 使用率百分比为服务器处于空闲状态时的数据。

连接数 Indy 默认 IOHandler Indy IOCP IOHandler
100 0% (4.1MB) 0% (3.9MB)
5000% (17.1MB)0% (7.7MB)
10000% (32.2MB)0% (12.4MB)
15007.3% (46.8MB)0% (17.1MB)
200015.4% (61.6MB)0% (21.9MB)
250051.9% (76.5MB)0% (26.5MB)
300068.8% (91.7MB)0% (31.2MB)
350072.3% (106MB)0% (35.9MB)

当并发连接数超过 3000 时,Indy 服务器开始出现速度下降,这很可能是由于线程上下文切换导致的,服务器空闲时 CPU 使用率也非常高。

IOCP 服务器在空闲状态下 CPU 使用率为零,内存消耗也更低。

下一个测试衡量连接 3000 个客户端所需的时间,每个客户端连接服务器后发送一条消息,服务器将该消息回显。

Indy 默认 IOHandler Indy IOCP IOHandler
连接 3000 个客户端并回显消息 15.32 seconds 6.89 seconds

性能测试在搭载 16 核处理器和 32GB 内存的 Windows Server 2022 上进行。