• 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

    you are the best!
  • 相关阅读:
    POJ1806 Manhattan 2025
    POJ1258 AgriNet【最小生成树】
    POJ1789 Truck History【最小生成树】【终于AC了】
    memset的用法
    HDOJ1106 排序
    POJ2965
    414某OJ竞赛题
    HDOJ1745 I hate it【线段树】
    HDOJ2795 Billboard【线段树】
    蓝桥杯o(︶︿︶)o 唉
  • 原文地址:https://www.cnblogs.com/linguoguo/p/15474508.html
Copyright © 2020-2023  润新知