技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> 其他 --> Golang socket 里面奇怪的 pipe 使用

Golang socket 里面奇怪的 pipe 使用

浏览:461次  出处信息

有个 golang 写的 proxy server, 大概日常 tcp 连接数两万多左右,结果某次在 /proc/pid/fd 下面一看,竟然有五到六万多文件,ls -l 一看,居然 socket 只有两万多,pipe 反而有三万多小四万,这就奇了怪了,哪儿来的这么多 pipe?

读了一阵子源码搞清楚了,golang 在 Linux 下面,对于 fd 对拷这种操作【具体是 net.Conn.readFrom(net.Conn)】,有个用 splice 系统调用的优化,会先试着用 splice 调用在内核里面完成两个 fd 之间的拷贝,这个可以省去将大量数据从 kernel 里面拷贝到 user space 的操作。如果失败才正常拷贝。

然而 splice 这个调用可能是为了内部实现方便,目标一方必须是 pipe 类型的 fd。所以 golang 里面的实现其实比较龌龊,先创建一对 pipe fd,然后从源 fd splice 进 pipe 入端,接下来从 pipe 出端 splice 到目标 fd。 这样下来一个 readFrom 操作,里面要一次 pipe2 调用,2 次 splice 调用,还有 2 次 close 操作关掉 pipe。有趣的是,即使这么龌龊的实现,在数据量大的应用,比如 proxy 上面,依然可以达到比直接拷贝更好的性能,可以参考下面的第一个链接。

唯一感觉比较不爽的也就是每次 readFrom 都要创建 pipe 再销毁了,这个为了不影响 golang 的架构设计,可能也只能这么做。不过一般 proxy 里面最后大多是 io.Copy ,而这个调用一旦调用就直到 tcp 连接断开了,生命周期不会太短,所以完全没有必要再做任何优化了。

参考传送门

https://github.com/golang/go/issues/10948
https://github.com/golang/go/blob/0e85fd7561de869add933801c531bf25dee9561c/src/net/tcpsock_posix.go#L47
https://man7.org/linux/man-pages/man2/splice.2.html


建议继续学习:

  1. 推荐一些socket工具,TCP、UDP调试、抓包工具    (阅读:9280)
  2. 推荐一些socket工具,TCP、UDP调试、抓包工具    (阅读:7033)
  3. 用unix socket加速php-fpm、mysql、redis的连接    (阅读:6282)
  4. 浅析linux kernel network之socket创建    (阅读:5528)
  5. nginx、php-fpm默认配置与性能–TCP socket还是unix domain socket    (阅读:4826)
  6. web socket 心跳包的实现方案    (阅读:4776)
  7. python中的socket代理    (阅读:4656)
  8. netstat和web主机socket文件分析    (阅读:4285)
  9. 使用socket.io和node.js搭建websocket应用    (阅读:4239)
  10. php socket为什么这么慢,直到超时    (阅读:3649)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1