5 ms·
You can do this with TCP keepalives [0]. Under Linux, a process can enable the SO_KEEPALIVE option on sockets to request that the Linux kernel send TCP keepali
by mleonhard 6y ago
You can do this with TCP keepalives [0]. Under Linux, a process can enable the SO_KEEPALIVE option on sockets to request that the Linux kernel send TCP keepalives periodically. A kernel option determines how frequently the kernel sends TCP keepalive packets. It is a single option that applies to all sockets of all processes. One can also configure the OS to enable SO_KEEPALIVE by default on all sockets of all processes.
Golang's GRPC library implements keepalives at the GRPC protocol level [1]. It provides a `Context` value [2] that code can use to detect peer disconnect and cancel expensive operations.
Golang's HTTP server API does not provide any way to detect peer disconnect before sending the final response [3].
Rust cannot set SO_KEEPALIVE [4]. One could possibly implement keepalives by writing zero-length chunks to the socket.
Java's Netty server library can set SO_KEEPALIVE [5]. One can then code a request handler that periodically checks if the socket is connected [6] and cancels expensive operations. Unfortunately, there is standard tooling to do this.
EDIT: You did mention TCP keepalives. I was not aware that some routers drop them. Can you link to any data on the prevalence of tcp-keepalive dropping for various kinds of client connections: home router, corporate wifi, mobile carrier-grade-NAT?
[0] https://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html https://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html
[1] https://pkg.go.dev/google.golang.org/grpc/keepalive https://pkg.go.dev/google.golang.org/grpc/keepalive
[2] https://pkg.go.dev/google.golang.org/grpc#ServerStream https://pkg.go.dev/google.golang.org/grpc#ServerStream
[3] https://pkg.go.dev/net/http#HandlerFunc https://pkg.go.dev/net/http#HandlerFunc
[4] https://github.com/rust-lang/rust/issues/69774 https://github.com/rust-lang/rust/issues/69774
[5] https://netty.io/4.1/api/io/netty/channel/ChannelOption.html#SO_KEEPALIVE https://netty.io/4.1/api/io/netty/channel/ChannelOption.html...
[6] https://netty.io/4.1/api/io/netty/channel/Channel.html#isOpen-- https://netty.io/4.1/api/io/netty/channel/Channel.html#isOpe...
- derefr 6y agoI can't offer any data myself, but I can suggest that chasing up the reason that more "modern" runtimes like Go's and Rust's don't bother to expose SO_KEEPALIVE support — i.e. the discussions that ensued when someone proposed adding this support, as they certainly did at some point — would be a good place to find that data cited. I can point out the obvious "analytical evidence", though: note how all the platform APIs that did expose SO_KEEPALIVE are from the 90s at the latest — i.e. before the proliferation of L4 middleboxes. And note how modern protocols like Websockets, gRPC, and even HTTP/2 (https://webconcepts.info/concepts/http2-frame-type/0x6 https://webconcepts.info/concepts/http2-frame-type/0x6) always do their own L7 keepalives, rather than relying on TCP keepalives — even when there's no technical obstacle to relying on TCP keepalives.
- deleted 6y ago[deleted]
- ainar-g 6y ago> Golang's HTTP server API does not provide any way to detect peer disconnect before sending the final response [3]. Iirc, the context mechanism can be used to detect the client's disconnection or cancellation of the request in some cases. From [1]: > For incoming server requests, the context is canceled when the client's connection closes, the request is canceled (with HTTP/2), or when the ServeHTTP method returns. [1]: https://golang.org/pkg/net/http/#Request.Context https://golang.org/pkg/net/http/#Request.Context
- mleonhard 6y agoGood. Thanks.