【问题标题】:Broken pipe appears when request http service through unix domain socket通过 unix 域套接字请求 http 服务时出现损坏的管道
【发布时间】:2021-02-09 02:24:26
【问题描述】:
# go version
go version go1.13.9 linux/amd64
# uname -a
Linux iZ8vbaym9jmge8qd5hlcpiZ 4.15.0-111-generic #112-Ubuntu SMP Thu Jul 9 20:32:34 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

http服务器如下:

package main

import (
    "fmt"
    "log"
    "net/http"
    "os"
    "os/signal"
    "syscall"
    "time"
  _ "net/http/pprof"
)

func main() {

    h2 := func(w http.ResponseWriter, _ *http.Request) {
        time.Sleep(2 * time.Second)
        fmt.Println("555555")
        if _, err := w.Write(make([]byte, 9999)); err != nil {
            fmt.Println("---=====: ", err.Error(), syscall.EPIPE == err)
            return
        }
    }
  go func() {
      log.Println(http.ListenAndServe(":6060", nil))
  }()
    http.HandleFunc("/endpoint", h2)
    sigs := make(chan os.Signal, 1)
    signal.Notify(sigs, syscall.SIGPIPE)
    go func() {
        sig := <-sigs
    fmt.Println("6666666666", sig.String())
        fmt.Println(sig)
    }()
    log.Fatal(http.ListenAndServe(":8888", nil))
}

1、通过unix域套接字

卷曲请求 curl 127.0.0.1:8888/endpoint -m 0.2 结果:

555555
---=====:  write tcp 127.0.0.1:8888->127.0.0.1:33794: write: broken pipe false
6666666666 broken pipe
broken pipe

2、通过tcp套接字

卷曲请求: curl 47.92.3.20:8888/endpoint -m 0.2 得到结果:555555

go 的 netpoll 是否以不同的方式处理 unix domain socket 和 tcp socket?我看不出 netpoll 代码有什么不同。

【问题讨论】:

    标签: linux sockets go


    【解决方案1】:

    您在连接处理中找不到任何区别,因为这两种情况的处理方式相同。这一点对 Go 来说并不特别,在 unix 套接字中,连接的写入端可以在连接关闭时立即检测到。

    在 TCP 套接字中,无法立即检测到已关闭的连接。您可以等待 recv 调用返回 0(或在 go 中返回 io.EOF),这在某些情况下会发生并且是如何取消 Request.Context,但它不能立即涵盖连接断开的情况。当远程主机在发送数据时离开时,您所能做的就是继续写入,直到 TCP 堆栈收到指示连接不再可用的 RST 或 ICMP 消息。一旦发生这种情况,在大多数类 unix 系统上,您都会从系统中收到相同的 broken pipe 错误。

    【讨论】:

    • unix socket是IPC就没有缓冲区吗?
    • @helios,抱歉,这令人困惑,所以我将其删除。有一个缓冲区,但实际上它更小,响应更快,因为只涉及本地进程。 “IPC”这个词在这里不相关,有很多东西可以用于 IPC
    • 谢谢大家的回答,现在有两个问题: 1、 通过TCP socket请求,为什么收到RST包却没有破管道? 2、为什么我在上面的go代码中减小response(9999 -> 1500)的大小没有破管错误?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-17
    • 1970-01-01
    • 1970-01-01
    • 2012-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多