A couple of flaws in creating a web application on Go

    If you are interested, what is the flaw in all Go web applications located on the hub? And if you want to know how to make your Go web application one step closer to production ready, then welcome to cat.

    An important difference between Go web programming is that as a result, you usually get a program that is a web server. Therefore, you become responsible for what the web server usually answers.

    If we compare what Hello World looks like in PHP and Go, then we will see

    Php


    Go

    package main
    import (
        "fmt"
        "net/http"
    )
    func handler(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
    }
    func main() {
        http.HandleFunc("/", handler)
        http.ListenAndServe(":8080", nil)
    }
    

    Taken from the Go language site wiki .

    Similar code is used in the following articles on the hub: Web development on Go , We write a web terminal emulator on Go using Websocket , Goblog: Home-made static engine for a blog on Go , Writing your Web application on Go .

    I myself in the article My Certificate Authority - in 5 OpenSSL teams , gave a similar example on Go.

    Related: Go Language. A small client-server application , TCP / IP proxy on Go .

    An important difference and advantage of Go is how Go works with the network and can hold many open connections, for example, to implement long polling.

    In the article C10k (Problem 10000 connections) in different languages ​​/ platforms Go showed the second result after Erlang, opening 9775 connections out of 10000.

    Go's second advantage is simplicity and readability of the code, ease of learning, which makes it often the number 1 choice when developing applications where you need to work with many open connections.

    Error The flaw of all these examples


    The disadvantage is that Timeout (Deadline) for connections is 0 by default (i.e. timeout is not set at all). If the client does not send a packet that the connection is closed, then such a connection will hang forever. This will block goroutine in standby mode until the end of the life of the web server. The number of open connection resources is usually limited. By default, in Linux, an application can open 1024 files (TCP connection is equal to a file).

    This means a server created on Go as follows

    http.ListenAndServe(":8080", nil)
    

    It will gradually accumulate non-closed compounds and will drown in them every other day, month or year.

    Therefore, it is important to set the Timeout, which in the default web servers are installed by default.

    for example

    	// log.Fatal(http.ListenAndServe(":8085", nil))
    	{
    		s := &http.Server{
    			Addr:           ":8085",
    			Handler:        nil,
    			ReadTimeout:    1000 * time.Second, 
    			WriteTimeout:   1000 * time.Second,
    			MaxHeaderBytes: 1 << 20,
    		}
    		log.Fatal(s.ListenAndServe())
    	} 
    

    The second drawback is the parameter that is often indicated in a regular web server is the maximum number of connections that the web server is ready to open. If this limitation is reached, the web server begins to sacrifice keep-alive connections or to give an error and close the connections.

    Go doesn’t do this by default, and it’s not at all obvious how to limit the number of connections in Go or calculate the number of connections, or even less control this process.

    To understand how to manage connections, you need to look at the sources of func (* Server) ListenAndServe and func (* Server) ListenAndServeTLS , then we will see that both functions use the func (* Server) Serve function .

    This function receives the net.Listener interface as an argument.
    Here we can implement it to limit and control the connections.
    An example of a wrapper around the net.Listener interface is LimitListener

    Having gone through the articles on the hub with the [go] tag, I did not find examples in which Timeout, DeadLine were installed or the number of connections was controlled.

    Considering that Go was created as a super-parallel, network language, the implementation of the correct and well-thought-out strategy in working with connections is an essential element of the Go application.

    Also popular now: