我有以下内容:
//In an init func
if logStashHost != "" {
lsconn, err = net.Dial("tcp", logStashHost)
}
...
ToLogStash(rec, lsconn)
然后有两个功能:
func ReadLogStash(conn net.Conn) {
buffer := make([]byte, 256)
for {
_, err := conn.Read(buffer)
if err != nil {
fmt.Println(err)
} else {
fmt.Println(buffer)
}
}
}
func ToLogStash(r *logrow.Record, conn net.Conn) {
b, err := json.Marshal(r)
if err != nil {
fmt.Println(err)
return
}
_, err = fmt.Fprintln(conn, string(b))
if err != nil {
fmt.Println(err)
}
}
ReadLogStash是一个正在运行的goroutine。如果对方关闭,我会得到EOF。 ReadLogStash中有什么好的实现让它在获得EOF时每隔X秒尝试重新建立连接?
答案 0 :(得分:6)
Go有同步和通信的渠道,使用它们!
在循环中建立连接,让它等待某种消息返回到频道。
...
errCh := make(chan error)
for {
lsconn, err = net.Dial("tcp", logStashHost)
// check error!
go ReadLogStash(lsconn, errCh)
err = <-errCh
if err != nil {
// bad error
break
}
// sleep to backoff on retries?
}
...
func ReadLogStash(conn net.Conn, errCh chan error) {
_, err := io.Copy(os.Stderr, conn)
if err != nil {
fmt.Println(err)
}
// a nil error from io.Copy means you reached EOF.
errCh <- err
}
除非你在ReadLogStash中有更多的功能,否则你可能只是使用io.Copy内联,而忘记了整个函数,但无论如何这种模式对你有用。
答案 1 :(得分:1)
这是我最终的目标,一个渠道是正确的方向:
if logStashHost != "" {
lsc = make(chan *logrow.Record)
go ToLogStash(lsc, logStashHost)
}
...
if lsc != nil {
lsc <- rec
}
...
func ToLogStash(c chan *logrow.Record, logStashHost string) {
var lsconn net.Conn
var enc *json.Encoder
var err error
connect := func() {
for {
lsconn, err = net.Dial("tcp", logStashHost)
if err == nil {
enc = json.NewEncoder(lsconn)
break
}
log.Println(err)
time.Sleep(time.Second)
}
}
connect()
for r := range c {
err = enc.Encode(r)
if err != nil {
lsconn.Close()
log.Println(err)
connect()
}
}
}