所以我尝试使用流利的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()
}
答案 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
}