golang unix socket错误。拨号:资源暂时不可用

时间:2015-05-14 02:53:13

标签: sockets unix go

所以我尝试使用流利的unix套接字进行日志记录任务并偶尔发现错误

  

拨打:{socket_name}资源暂时不可用

关于为什么会发生这种情况的任何想法?

我尝试添加"重试"逻辑,减少错误,但它仍然有时发生。

另外,对于fluntd,我们使用unix套接字通信的默认配置

func connect() {

var connection net.Conn
var err error
for i := 0; i < retry_count; i++ {
    connection, err = net.Dial("unix", path_to_socket)
    if err == nil {
        break

    }
    time.Sleep(time.Duration(math.Exp2(float64(retry_count))) * time.Millisecond)
}
if err != nil {
    fmt.Println(err)

} else {
        connection.Write(data_to_send_socket)

    }
     defer connection.Close()
}

2 个答案:

答案 0 :(得分:2)

Go以非阻塞模式创建其套接字,这意味着通常会阻塞的某些系统调用。在大多数情况下,它会通过等待套接字准备好读/写来透明地处理EAGAIN错误(“资源暂时不可用”消息所指示的内容)。尽管connect中的Dial调用似乎没有这个逻辑。

如果其侦听队列已填满,connect在连接到UNIX域套接字时可能会返回EAGAIN。如果客户端以比接受它们更快的速度连接它,就会发生这种情况。 Go应该在套接字上等待,直到它在这种情况下变得可连接并重试类似于它对Read / Write的作用,但它似乎没有那个逻辑。

因此,最好的办法是等待并重试Dial来处理错误。那或者说明为什么你的服务器没有及时接受连接。

答案 1 :(得分:0)

对于指数退避,您可以使用此库:github.com/cenkalti/backoff。我认为你现在拥有它的方式总是在相同的时间内睡觉。

对于网络错误,您需要检查它是否是临时错误。如果是,则重试:

type TemporaryError interface {
    Temporary() bool
}

func dial() (conn net.Conn, err error) {
    backoff.Retry(func() error {
        conn, err = net.Dial("unix", "/tmp/ex.socket")
        if err != nil {
            // if this is a temporary error, then retry
            if terr, ok := err.(TemporaryError); ok && terr.Temporary() {
                return err
            }
        }
        // if we were successful, or there was a non-temporary error, fail
        return nil
    }, backoff.NewExponentialBackOff())
    return
}