Indy 服务器 — Linux EPOLL(3 / 3)

· 功能

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

EPOLL IOHandler 仅在 sgcWebSockets Enterprise 包中提供。


配置

Linux 上的 EPOLL 是一种 API,允许使用有限的线程池处理数千个连接,而不是像 Indy 默认那样为每个连接使用一个线程。

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

Server.IOHandlerOptions.IOHandlerType := iohEPOLL;
Server.IOHandlerOptions.EPOLL.EPOLLThreads := 0; // the number of EPOLL threads will be calculated automatically using the number of processors.
Server.IOHandlerOptions.EPOLL.WorkOpThreads := 0; 

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

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

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

性能测试

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

连接数 Indy 默认 IOHandler Indy EPOLL IOHandler
100 1% (1.4MB) 0% (1.4MB)
5004% (5.6MB)0% (4.8MB)
100010% (10.5MB)0% (8.9MB)
1500-- (Failed)0% (13.3MB)
2000-- (Failed)0% (17.4MB)

Indy 服务器由于 Select 方法最多只能接受 1024 个并发连接的限制,无法建立超过 1024 个并发连接。在 1000 个连接以内的对比中,Indy 默认服务器的 CPU 使用率和内存消耗均高于 EPOLL 服务器。EPOLL 服务器在空闲状态下 CPU 使用率为零,内存消耗也更低。

下一个测试衡量连接 X 个客户端所需的时间。

连接数 Indy 默认 IOHandler Indy EPOLL IOHandler
1000 16.5 seconds 9.49 seconds
10000-- (Failed)1min 55 seconds

测试在搭载 2 个处理器和 8GB 内存的 Ubuntu 20.04 虚拟机上进行。

EPOLL 文档

https://man7.org/linux/man-pages/man7/epoll.7.html

实现 EPOLL 的优秀 Delphi 项目

https://github.com/winddriver/Delphi-Cross-Socket
https://github.com/grijjy/GrijjyFoundation