EPOLL

Supported by

 

  TsgcWebSocketServer

  TsgcWebSocketHTTPServer

 

*Requires sgcWebSockets Enterprise Edition.

 

EPOLL for Linux is an API that allows handling thousands of connections using a limited pool of threads instead of using one thread per connection as Indy does by default.

To enable EPOLL for Indy Servers, Go to IOHandlerOptions property and select iohIEPOLL as IOHandler Type.


Server.IOHandlerOptions.IOHandlerType := iohEPOLL;
Server.IOHandlerOptions.EPOLL.EPOLLThreads := 0;
Server.IOHandlerOptions.EPOLL.WorkOpThreads := 0;
Server.IOHandlerOptions.EPOLL.PartialRequestTimeout := 0;
Server.IOHandlerOptions.EPOLL.TCPKeepAlive.Enabled := True;
Server.IOHandlerOptions.KeepAliveTimeout := 120;

 

EPOLLThreads are the threads used for EPOLL asynchronous requests (overlapped operations), by default the value is zero which means the number of threads are calculated using the number of processors (except for Delphi 7 and 2007 where the number of threads is set to 32 because the function cpucount is not supported). You can adjust the number of threads manually.

WorkOpThreads sets the minimum number of worker threads kept ready to process requests, 0 by default. An EPOLL thread only detects that a socket is ready and hands the work to this pool, so it never blocks on a slow client. The pool grows on demand up to a fixed maximum whenever every worker is already busy, so it does not need to be sized in advance. Raise this value only if you want the pool already warm before the first request, which avoids paying for thread creation during an initial burst of connections.

Changed in 2026.9.0. WorkOpThreads used to pin every connection to one of these threads, so all requests on a connection ran on the same thread, and WorkOpRoundRobin chose how new connections were distributed over them. Pinning has been removed: a connection parked waiting for the rest of a request blocked every other connection assigned to the same thread, which stalled the server. Requests on the same connection can now run on different threads, so anything held per thread, such as a database connection or a thread-local cache, must no longer be assumed to follow a connection. WorkOpRoundRobin no longer exists. Remove it from your code, and if you enabled it in the Object Inspector, delete the WorkOpRoundRobin line from the form's .dfm as well, otherwise the form does not load.

PartialRequestTimeout lets the server wait for the rest of an HTTP request body whose length it already knows, in milliseconds and 0 by default, which disables it. Without it, a request body that does not all arrive within a single readiness event, for example a large POST sent in several packets, is silently dropped and the connection closed with no reply. The wait never runs on an EPOLL thread, which services many connections and must never block, it runs on the worker pool described above, which grows on demand up to a fixed maximum, so a slow or unresponsive client cannot exhaust it and hold back the other connections.

TCPKeepAlive lets the operating system probe idle connections and detect a peer that has silently disappeared (disabled by default). When TCPKeepAlive.Enabled is set to True, the O/S starts probing a connection after it has been idle for TCPKeepAlive.Time seconds (60 by default), repeating every TCPKeepAlive.Interval seconds (10 by default) until the peer answers or the connection is dropped.

KeepAliveTimeout closes any connection that has been idle for longer than the given number of seconds (0 by default, which means disabled). Only idle connections are affected, a request that is being read or a response that is being written is never interrupted by this timeout. This is the closest match to how the default thread-per-connection IOHandler frees a silent connection, and it does not depend on the operating system or on any cooperation from the peer.

 

Enabling EPOLL for Linux servers is recommended when you need to handle thousands of connections. If your server is only handling a maximum of 100 concurrent connections, you can stay with the default Indy thread model.

 

 

OnDisconnect event not fired

 

EPOLL works differently from default indy IOHandler. With default indy IOHandler, every connection runs in a thread and these thread are running all the time and checking if connection is active, so if there is a disconnection, it's notified in a short period of time.

 

EPOLL works differently, there is a thread pool which handles all connections, instead of 1 thread = 1 connection like indy does by default. For EPOLL, the only way to detect if a connection is still alive is trying to write in socket, if there is any error means that connection is closed. There are 3 options to detect disconnections:

 

1. If you use TsgcWebSocketClient, you can enable it in Options property, CleanDisconnect := True (by default is disabled). If it's enabled, before the client disconnects it sends a message informing the server about disconnection, so the server will receive this message and the OnDisconnect event will be raised.

2. You can enable heartbeat on the server side, for example every 60 seconds, so it will try to send a ping to all clients connected and if there is any client disconnected, OnDisconnect will be called.

3. You can enable TCPKeepAlive and/or set KeepAliveTimeout on the server's IOHandlerOptions. These let the server itself detect a peer that has gone silent, for example because the client crashed or the network connection dropped without sending a close message, and close the connection, without depending on the client sending anything.

 

Linux Connections Limit

 

If you want to increase the number of concurrent open connections use the following command

 

ulimit -n 10000

 

The previous command sets the max number of open files descriptors to 10000