Threaded web servers start (or use) a new OS thread per connection.
This severely limits scaling, because every new thread gets its own copy of the stack, which can be 2-4MB.
I imagine that copy-on-write can be helpful here.
Nginx uses an event loop – is this true? I had no idea.
Blocking operations kill perf in an evented web server.
Goroutines are cheap, but file descriptors (which TCP connections are, too) are not, so remember to close connections diligently. TCP connections can be reused after a timeout, so this isn’t automatic.
Go uses a Linux
splice syscall to copy data from one net.Conn to another, which allows for an extremely terse implementation of a proxy server that’s also very performant. The connection payload never touches userspace. https://github.com/golang/go/issues/10948
This works even when the copy uses a “generic” io.Copy that doesn’t know anything about networking in particular because of interface upgradation.
MultiReader allows you to construct a reader from many readers, which is useful when you’ve read some data from net.Conn but want to pass it through as if it were untouched.
Touched on the idea of net.Conn wrappers, which are possible because Go’s interfaces are composable.