Add socket activation support for TCP and UDS servers#2734
Add socket activation support for TCP and UDS servers#2734AndreeaDrehuta wants to merge 3 commits into
Conversation
|
|
Adds an opt-in "socket-activation" feature that lets tonic servers accept pre-opened listeners passed by a supervisor (e.g. systemd) for both TCP and Unix domain sockets. Includes examples, systemd unit files, test scripts, and unit tests.
8468066 to
9ea4aa1
Compare
5bd8c0e to
33a0062
Compare
|
Hello! @gu0keno0 @dfawley @sauravzg @LYZJU2019 Thanks in advance for your time and feedback! |
I'm OOO this week and can take a deeper look at the code once back. Just want to better understand the motivation, what's the memory overhead you observed in production? Tonic is highly memory-efficient. A mostly dormant server / client should consume less than 100 MB of RSS if you use system glibc / mialloc. Also, cc: @LucioFranco |
We haven't observed any significant memory issues with Tonic. Our service currently consumes roughly ~30 MB, which is already quite low. However, since we're hardware-constrained and run multiple services on the same infrastructure, we're paying close attention to resource utilization and looking for opportunities to optimize further. |
|
@AndreeaDrehuta this feels quite custom and probably something that we don't want to include in tonic but this is probably a good candidate for providing a custom transport that allows you to use this feature. |
Adds an opt-in "socket-activation" feature that lets tonic servers accept pre-opened listeners passed by systemd for both TCP and Unix domain sockets. Includes examples, systemd unit files and unit tests.
Fixes #2733
Motivation
Under systemd, a service can be started on-demand when a client connects. The manager creates and listens on the socket itself, then passes the already-listening file descriptor to the spawned process via the
LISTEN_FDS/LISTEN_PIDenvironment variables.Consider a gRPC server that receives requests only occasionally. Keeping it running around the clock just to answer the rare request wastes memory and other resources. A better fit for that situation is to let the process run only while it is actually serving requests: the service manager (systemd) holds the socket, starts the server on an incoming connection, and the server can stop itself once it goes idle, after which the manager re-activates it on the next connection.
Solution
Introduces a new, opt-in socket-activation cargo feature (Unix only, disabled by default, so there is no impact on existing users).
When the feature is enabled, socket binding checks for an inherited listener before opening a new one:
TCP: TcpIncoming::bind(addr) adopts an inherited listening socket whose address matches addr, if none was passed in, it falls back to binding normally.
UDS: the Unix domain socket path binding adopts a matching inherited listener when present, otherwise binds as usual.
Implementation details:
A helper (socket_activation.rs) reads LISTEN_PID / LISTEN_FDS, verifies the fds were intended for this process, and returns the first inherited fd that is a listening stream socket matching the requested address.
Behavior is fully backward compatible: with the feature off, or when no fds are passed in, binding works exactly as before.
Also included to make the feature usable and testable:
Example TCP and UDS client/server binaries under examples/src/socket_activation/.
Ready-to-use systemd .socket / .service unit files.
Shell test scripts (test_tcp.sh, test_uds.sh) that exercise the activation flow end to end.
Unit tests covering fd scanning and listening-socket detection.