http.HandleFunc 注册的 handler 触发时是串行的还是并发的?

阅读 3.6k
1 个回答

http.Handler是并发执行。

当srv接受一个请求后,会调用http.ServeMux.ServeHTTP处理这个请求,http.ServeMux.ServeHTTP -> http.ServeMux.Handler -> http.ServeMux.handler,ServeMux这个顺序是串行的,但是http.Server for Accept go serve是并行的

// https://golang.org/src/net/http/server.go L2900
    for {
        rw, err := l.Accept()
        if err != nil {
            select {
            case <-srv.getDoneChan():
                return ErrServerClosed
            default:
            }
            if ne, ok := err.(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", err, tempDelay)
                time.Sleep(tempDelay)
                continue
            }
            return err
        }
        connCtx := ctx
        if cc := srv.ConnContext; cc != nil {
            connCtx = cc(connCtx, rw)
            if connCtx == nil {
                panic("ConnContext returned nil")
            }
        }
        tempDelay = 0
        c := srv.newConn(rw)
        c.setState(c.rwc, StateNew) // before Serve can return
        go c.serve(connCtx)
    }

c.serve这个地方就开始请求并发了,后续*conn读取net.Conn数据,构建http.Request和http.ResponseWriter对象,然后调用srv.Handler对象执行请求(L1895 -> L2799 -> L2807处理默认Handler),但是srv.Handler对象当前说的这种情况下值为http.ServeMux,所以下一步执行就从http.ServeMux.ServeHTTP开始。

推荐问题