我有一个go程序,它连接到tcp服务器并将该消息发布到Web服务。该应用程序在第一次运行时工作正常,并在一周左右后发生恐慌。我不知道为什么。堆栈跟踪也没有帮助。 (我从mac os交叉编译到linux; env GOOS = linux GOARCH = 386 go build) 可能会有人指出可能存在的问题吗?
tcp服务器连接可能偶尔会关闭;我已经手工构建了重新连接逻辑。 错误条件也适用于发布。互联网连接可能随时中断;所以“dns”解析器默认使用“cgo”是恐慌。我使用“netgo”重新编译以使用纯粹的网络实现。
net.runtime_pollWait(0xf75c12d8, 0x72, 0x18690000)
/usr/local/go/src/runtime/netpoll.go:157 +0x55 net.(*pollDesc).Wait(0x18a6bb38, 0x72, 0x0, 0x0)/usr/local/go/src/net/fd_poll_runtime.go:73 +0x35
net.(*pollDesc).WaitRead(0x18a6bb38, 0x0, 0x0) _poll_runtime.go:78 +0x33
net.(*netFD).Read(0x18a6bb00, 0x18cd6000, 0x1000, 0x1000, 0x0, 0xf75bc018, 0x18690000)/usr/local/go/src/net/fd_unix.go:232 +0x19anet.(*conn).Read(0x18cd4d78, 0x18cd6000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
/usr/local/go/src/net/net.go:172 +0xb9
net/http.noteEOFReader.Read(0xf75fc018, 0x18cd4d78, 0x1889770c, 0x18cd6000, 0x1000, 0x1000, 0x2c3620, 0x0, 0x0)
/usr/local/go/src/net/http/transport.go:1370 +0x55
net/http.(*noteEOFReader).Read(0x18cd29e0, 0x18cd6000, 0x1000, 0x1000, 0x8056f0c, 0x0, 0x0)
<autogenerated>:126 +0xae
bufio.(*Reader).fill(0x1881b7d0)
/usr/local/go/src/bufio/bufio.go:97 +0x172
bufio.(*Reader).Peek(0x1881b7d0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0)
/usr/local/go/src/bufio/bufio.go:132 +0xad
net/http.(*persistConn).readLoop(0x188976e0)
/usr/local/go/src/net/http/transport.go:876 +0xe3
created by net/http.(*Transport).dialConn
/usr/local/go/src/net/http/transport.go:685 +0xabc
GO程序go program
package main
import (
"bufio"
"bytes"
"encoding/json"
"flag"
"fmt"
"net"
"net/http"
"time"
)
var (
server = flag.String("deamon", "127.0.0.1:7070", "AMQP URI")
msgRoutingKey = flag.String("routingKey", "routingKey", " routing key")
msgexchange = flag.String("exchange", "exchange", " excahnge ")
mywebserviceServer = flag.String("mywebservice-server", "127.0.0.1:8080", "mywebserviceServer:port ")
)
func init() {
flag.Parse()
}
type TcpConnector struct {
Outbound chan string
Inbound chan string
Addr string
ReconnectTime time.Duration
}
type Message struct {
RoutingKey string `json:"routingKey"`
Exchange string `json:"exchange"`
Data string `json:"data"`
}
func main() {
start := time.Now()
tcpClient := NewTcpConnector(*server)
elapsed := time.Since(start)
fmt.Println("the connecting params are %s", *server, *msgexchange, *msgRoutingKey, *mywebserviceServer)
fmt.Println("connecting to daemon took %s", elapsed)
go func() {
for msg := range tcpClient.Inbound {
fmt.Println(msg)
rabbitMessage := Message{
RoutingKey: *msgRoutingKey,
Exchange: *msgexchange,
Data: msg,
}
mywebserviceMessageEndpoint := fmt.Sprintf("http://%s/v1/messages/publish", *mywebserviceServer)
doPut(mywebserviceMessageEndpoint, &rabbitMessage)
}
}()
select {}
}
func doPut(url string, rabbitMessage *Message) {
start := time.Now()
b, err := json.Marshal(rabbitMessage)
client := &http.Client{}
request, err := http.NewRequest("PUT", url, bytes.NewBuffer(b))
request.Header.Add("Content-Type", "application/json")
request.Header.Add("accept", "application/json")
response, err := client.Do(request)
if err != nil {
fmt.Println(err)
} else {
defer response.Body.Close()
fmt.Println(" ", response.StatusCode)
hdr := response.Header
for key, value := range hdr {
fmt.Println(" ", key, ":", value)
}
}
elapsed := time.Since(start)
fmt.Println("posting to mywebservice took %s", elapsed)
}
func NewTcpConnector(addr string) *TcpConnector {
tcpConnector := &TcpConnector{
Addr: addr,
Outbound: make(chan string, 100),
Inbound: make(chan string, 100),
ReconnectTime: 30 * time.Second,
}
tcpConnector.connect()
return tcpConnector
}
//keep connect private, will be in trouble if got called twice
func (tcpConnector *TcpConnector) connect() {
conn, err := net.Dial("tcp", tcpConnector.Addr)
if err != nil {
fmt.Println("Failed to make a connection", err)
time.Sleep(tcpConnector.ReconnectTime)
tcpConnector.connect()
return
}
go func() {
for msg := range tcpConnector.Outbound {
_, err = fmt.Fprintf(conn, msg+"\n")
if err != nil {
fmt.Println("Failed sending event", err)
time.Sleep(tcpConnector.ReconnectTime)
tcpConnector.connect()
break
}
}
}()
go func() {
reader := bufio.NewReaderSize(conn, 1024*1024)
for {
message, err := reader.ReadBytes('\n')
if err != nil {
break
}
fmt.Println("Message Received: %s", message)
tcpConnector.Inbound <- string(message)
fmt.Println("Message sent to chan")
}
fmt.Println("reconnecting...")
tcpConnector.connect()
}()
fmt.Println("Connected tcp")
}