In some situations, you may need to adjust the default buffer sizes of a Golang HTTP server.
Adjusting the default buffer sizes allows you to benefit from higher throughput and improve the performance of your HTTP servers overall.
You may also tune the performance of your Linux kernel overall [if you are hosting your application on a Linux system]
I recommend https://github.com/klaver/sysctl as a good starting point on this.
To avoid the occurrence of any inconveniences, please make sure not to blindly copy and then paste things. Feel free to check the documented comments above each kernel parameter before actually using it to learn what each parameter does :)
At the present, the Golang HTTP server does not have an option that allows you to configure the write buffer size for unknown reasons.
The net/http
package will use a hard coded 4 KB buffer size for the response writer.
To modify this, check out https://github.com/oddmario/go-http-server-custom-write-buffer-patch
- Recommended tuned value: a value of 8 KB to 1 MB should be optimal for a higher throughput.
This is achievable by wrapping the TCP listener around our own custom interface that sets the TCP buffer size(s) right after accepting a connection.
// customListener wraps a TCPListener and sets the write buffer size for each connection
type customListener struct {
*net.TCPListener
writeBufferSize int
}
// Accept waits for and returns the next connection to the listener, setting the write buffer size
func (ln *customListener) Accept() (net.Conn, error) {
conn, err := ln.TCPListener.Accept()
if err != nil {
return conn, err
}
tcpConn, ok := conn.(*net.TCPConn)
if ok {
tcpConn.SetWriteBuffer(ln.writeBufferSize)
}
return conn, err
}
func main() {
listenerAddr := ":8080"
srv := &http.Server{
Addr: listenerAddr,
WriteBufferSize: 256 * 1024, // requires https://github.com/oddmario/go-http-server-custom-write-buffer-patch
Handler: /* handler here */,
}
ln, err := net.Listen("tcp", listenerAddr)
if err != nil {
fmt.Println("Error starting listener:", err)
return
}
tcpListener := &customListener{ln.(*net.TCPListener), 256 * 1024}
err := srv.Serve(tcpListener)
if err != nil {
fmt.Println(err)
return
}
}
If you would like, you can also modify the above code to adjust the TCP read buffer size.
Note that Golang can't set a TCP buffer size that exceeds the kernel's max rmem/wmem value. So make sure to adjust the kernel parameters accordingly for the application-level TCP buffer size(s) to take effect.
- Recommended tuned value: a value of 4 KB to 4 MB.