Process Management for the Go Webserver

前端 未结 2 1222
傲寒
傲寒 2020-11-27 21:29

I\'m a new Go programmer, coming from the world of web application and service development. Apologies is this is a herp de-derp question, but my googling around for an answ

2条回答
  •  一个人的身影
    2020-11-27 22:24

    ListenAndServe starts an HTTP server with a given address and handler. The handler is usually nil, which means to use DefaultServeMux. Handle and HandleFunc add handlers to DefaultServeMux.

    Look at http.Server, alot of fields are optional and works fine with default values.

    Now lets look at http.ListenAndServe, is not hard at all

    func ListenAndServe(addr string, handler Handler) error {
        server := &Server{Addr: addr, Handler: handler}
        return server.ListenAndServe()
    }
    

    so the default server is super simple to create.

    func (srv *Server) ListenAndServe() error {
        addr := srv.Addr
        if addr == "" {
            addr = ":http"
        }
        ln, err := net.Listen("tcp", addr)
        if err != nil {
            return err
        }
        return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
     }
    
    func (srv *Server) Serve(l net.Listener) error {
        defer l.Close()
        if fn := testHookServerServe; fn != nil {
            fn(srv, l)
        }
        var tempDelay time.Duration // how long to sleep on accept failure
        if err := srv.setupHTTP2(); err != nil {
            return err
        }
        for {
            rw, e := l.Accept()
            if e != nil {
                if ne, ok := e.(net.Error); ok && ne.Temporary() {
                    if tempDelay == 0 {
                        tempDelay = 5 * time.Millisecond
                    } else {
                        tempDelay *= 2
                    }
                    if max := 1 * time.Second; tempDelay > max {
                        tempDelay = max
                    }
                    srv.logf("http: Accept error: %v; retrying in %v", e, tempDelay)
                    time.Sleep(tempDelay)
                    continue
                }
                return e
            }
            tempDelay = 0
            c := srv.newConn(rw)
            c.setState(c.rwc, StateNew) // before Serve can return
            go c.serve()
        }
    }
    

    It Listen on "addr" and Accept every connection, then it spawns a goroutine to handle each connection independently. (HTTP/2.0 is a little bit different, but is the same in general).

    If you want to control connections you have 2 options:

    1. Create custom server (its 3 lines of code) with server.ConnState callback and control client connections from there. (but they will be Accepted by kernel anyway)

    2. Create custom server with your own implementation of net.Listener (like LimitedListener) and control connections from there, this way you will have ultimate power over connections.

    Since default http.Server has no way to be stopped the second way is the only way to gracefully terminate listener. You can combine two methods to implement different strategies, well its been done already.

提交回复
热议问题