Golang net/http

源码展示

  这里展示了 net/http 包的两个接口的源码:ListenAndServe、Serve

  ListenAndServe接口做了以下事情:

  • 设置地址类型
  • 生成侦听器
  • 开启Serve
func (srv *Server) ListenAndServe() error {
    if srv.shuttingDown() {
        return ErrServerClosed
    }
    addr := srv.Addr
    if addr == "" {
        addr = ":http"
    }
    ln, err := net.Listen("tcp", addr)
    if err != nil {
        return err
    }
    return srv.Serve(ln)
}

  Serve接口做了以下事情:

  • 检查是否有 server hook,有的话执行
  • 复制 listener
  • 设置 http2
  • trackListener,用于关闭时使用
  • 设置 baseCtx
  • 开启循环,监听接口,建立链接,给链接设置状态,然后为每个链接生成一个 goroutine 来循环执行请求
 1 func (srv *Server) Serve(l net.Listener) error {
 2     if fn := testHookServerServe; fn != nil {
 3         fn(srv, l) // call hook with unwrapped listener
 4     }
 5 
 6     origListener := l
 7     l = &onceCloseListener{Listener: l}
 8     defer l.Close()
 9 
10     if err := srv.setupHTTP2_Serve(); err != nil {
11         return err
12     }
13 
14     if !srv.trackListener(&l, true) {
15         return ErrServerClosed
16     }
17     defer srv.trackListener(&l, false)
18 
19     baseCtx := context.Background()
20     if srv.BaseContext != nil {
21         baseCtx = srv.BaseContext(origListener)
22         if baseCtx == nil {
23             panic("BaseContext returned a nil context")
24         }
25     }
26 
27     var tempDelay time.Duration // how long to sleep on accept failure
28 
29     ctx := context.WithValue(baseCtx, ServerContextKey, srv)
30     for {
31         rw, err := l.Accept()
32         if err != nil {
33             select {
34             case <-srv.getDoneChan():
35                 return ErrServerClosed
36             default:
37             }
38             if ne, ok := err.(net.Error); ok && ne.Temporary() {
39                 if tempDelay == 0 {
40                     tempDelay = 5 * time.Millisecond
41                 } else {
42                     tempDelay *= 2
43                 }
44                 if max := 1 * time.Second; tempDelay > max {
45                     tempDelay = max
46                 }
47                 srv.logf("http: Accept error: %v; retrying in %v", err, tempDelay)
48                 time.Sleep(tempDelay)
49                 continue
50             }
51             return err
52         }
53         connCtx := ctx
54         if cc := srv.ConnContext; cc != nil {
55             connCtx = cc(connCtx, rw)
56             if connCtx == nil {
57                 panic("ConnContext returned nil")
58             }
59         }
60         tempDelay = 0
61         c := srv.newConn(rw)
62         c.setState(c.rwc, StateNew) // before Serve can return
63         go c.serve(connCtx)
64     }
65 }

 

缺陷

  • 每个 connection 都生成 goroutine 来执行,goroutine 的数量会不可控,如果数量过多的话会导致调度效率降低,利用率低等情况

字节的网络库 - netpoll

https://mp.weixin.qq.com/s?__biz=MzI1MzYzMjE0MQ==&mid=2247485756&idx=1&sn=4d2712e4bfb9be27a790fa15159a7be1&chksm=e9d0c2dedea74bc8179af39888a5b2b99266587cad32744ad11092b91ec2e2babc74e69090e6&scene=21#wechat_redirect

posted @ 2021-10-28 11:39  林锅  阅读(74)  评论(0编辑  收藏  举报