Asynchronous Networking Patterns (in Go)

  • 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.
    • This works even when the copy uses a “generic” io.Copy that doesn’t know anything about networking in particular because of interface upgradation.
  • Go’s 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.