While most systems these days integrate over gRPC or HTTP, quite a few applications still speak custom protocols. And many of these custom protocols don't have handy packages like
net/http to manage all of the TCP connection creation and management.
Today's article is for anyone working directly with TCP connections. This article will discuss maintaining healthy TCP sessions over long periods and how to tune our system to keep sessions long-lived.
One of the most common problems for applications that manage long-lived TCP connections is keeping those connections healthy. Many factors are working against long-lived sessions. For example, firewalls often allow administrators to set a max idle session time. This idle timer will kill TCP sessions that haven't sent any data for an extended period.
Changes to clients and servers can also cause a session to be disconnected. But while one side might know of the disconnection right away, the other side might not find out until it tries to send a message.
One helpful way of preventing these dead connections is to enable TCP keepalive messages.
Keepalives are a feature of TCP that sends special packets after a period of inactivity. This packet contains no data but does require a TCP
ACK(Acknowledgement) packet to be returned. When the remote host receives the keepalive packet, they will acknowledge they received the packet by sending a
What's helpful with this design is that only one side of the connection needs to enable TCP keepalives. Because keepalives are a packet with the
ACK flag set to on, the TCP protocol requires the remote
ACK to be sent regardless of keepalive configuration.
To enable keepalives is very simple. With Go any
net.TCPConn type can have keepalives enabled by running the
net.TCPConn.SetKeepAlive() method with
true as the value.
The below example shows enabling keepalives from the server-side perspective.