我在读取套接字时遇到问题。有一个星号实例运行着大量调用(一分钟内10-60个),我正在尝试读取和处理与这些调用相关的CDR事件(连接到AMI)。
这是我正在使用的库(不是我的,但由于错误而被推到fork)https://github.com/warik/gami
它非常简单,主要操作在gami.go-readDispatcher中。
buf := make([]byte, _READ_BUF) // read buffer
for {
rc, err := (*a.conn).Read(buf)
所以,有一个TCPConn(a.conn)和大小为1024的缓冲区,我正在从套接字读取消息。到目前为止还不错,但最终会不时地(这个时间可能从10分钟到5小时不等,与通过套接字的数据量无关)读取操作失败,并出现io.EOF错误。我试图立即重新连接并重新登录,但这也是不可能的——连接超时,所以我不得不等待大约40-60秒,这段时间对我来说非常关键,因为延迟,我丢失了很多数据。我在谷歌上搜索,阅读资料,尝试了很多东西——什么都没有。最奇怪的是,在python或php中打开的简单套接字不会失败。
- 这个问题可能是因为缺少文件描述符来表示矿机或星号服务器上的套接字吗
- 星号配置中可能有这个问题吗(因为我有另一个星号,这个问题不会在上面重现,但我对最后一个星号的调用时间更少)
- 在我处理套接字连接或一般使用Go的方式中,有可能出现这个问题吗
go版本go1.2.1-linux/amd64
星号1.8
更新到最新星号。当AMI发送大量数据时,出现了类似的错误。
对于检查问题,您可以通过类似"command sip show peers"(或任何其他长输出命令)的ami命令进行发送,并查看结果。
好的,问题是操作系统套接字缓冲区溢出。似乎有太多的数据需要处理。
因此,有三种可能的方法来解决这个问题:
- 增加套接字缓冲区容量
- 以某种方式提高从套接字提取数据的处理速度
- 较低的数据量或频率
gami默认情况下从星号读取所有数据。我正在阅读所有的内容,并在实际阅读操作后对其进行过滤。根据AMI侦听应用程序在相当糟糕的PC上运行的情况,它似乎根本无法在缓冲区容量暴露之前读取所有数据。但是,通过向AMI发送"events"操作并指定所需的"EventMask",可以只接收特定的事件。所以,我决定这么做。并为不同的事件类型创建不同的连接。
我在读取数据时也遇到了问题。我不得不为它制作一个单独的线程(go例程),并通过chanel发送结果。然后它像闪电一样击中了我。读取本身会阻塞客户端rutin,因为它在等待结束(EOF),但给定的线程也必须做一些事情,而不仅仅是等待读取,因此读取必须在一个单独的线程(例程)中开始,这就是一个例子。它通过通道发送读取结果。
go func(mch chan string, conn net.Conn, ctx context.Context) {
reader := bufio.NewReader(conn)
for {
s, err := reader.ReadString('#')
if err != nil {
mch <- "[read stop] " + fmt.Sprint(err)
break
} else {
mch <- s
}
select {
case <-ctx.Done():
return
default:
za.SleepM(3)
}
}
}(mch, conn, ctx)