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
you are the best!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现