为什么通过 Amazon AMI 从 TCP 套接字读取数据一段时间后会出现 io.EOF 错误?

问题描述 投票:0回答:3

我在从套接字读取数据时遇到问题。有一个星号实例正在运行大量调用(一分钟 10-60 个),我正在尝试读取和处理与这些调用相关的 CDR 事件(连接到 Amazon 机器实例)。

这是我正在使用的库(不是我的,而是由于错误而分叉的)https://github.com/warik/gami

这非常简单;主要操作在 gami.go - readDispatcher 中。

buf := make([]byte, _READ_BUF)    // read buffer
    for {
        rc, err := (*a.conn).Read(buf)

因此,有一个 TCP 连接 (a.conn) 和一个大小为 1024 的缓冲区,我正在从套接字读取消息。到目前为止一切顺利,但最终(该时间可能从 10 分钟到 5 小时不等,与通过套接字传输的数据量无关),读取操作会失败并出现 io.EOF 错误。

我尝试立即重新连接并重新登录,但这不起作用;连接超时,所以我被迫等待大约 40-60 秒才能重新连接。这个时间延迟对我来说非常关键;由于延迟,我丢失了大量数据。在 Python 或 PHP 中打开这样一个简单的套接字不会以同样的方式失败。

可能是什么问题?

问题可能是由于:

  • 我的星号配置(我有另一个星号实例,没有这个问题,但我对最后一个星号实例的调用时间较少)
  • 我的套接字连接实现或一般的 Go 代码

但我不确定。有什么想法吗?

我正在使用 Go 1.2.1 linux/amd64 和 Asterisk 1.8。

sockets tcp go asterisk amazon-ami
3个回答
1
投票

更新至Asterisk最新版本(13.x); 1.8 已经落后了三个主要版本。以前的版本有一个错误,比如 AMI 发送大量数据时。

要检查问题,您已通过 AMI 命令(如

COMMAND sip show peers
)(或任何其他长输出命令)发送并查看结果。


-1
投票

问题出在操作系统套接字缓冲区溢出。 AMI 实例中似乎有太多数据需要处理。

有三种可能的方法可以解决此问题:

  • 增加套接字缓冲量
  • 提高从套接字读取数据的处理速度
  • 降低数据量或频率

默认情况下,Gami 读取 Asterisk 中的所有数据。我正在阅读所有这些内容,并在实际读取操作后过滤它们。由于 AMI 监听应用程序运行在资源非常有限的机器上,因此在超出缓冲区容量之前,它似乎无法读取所有数据。

但是,通过将“Events”操作发送到 AMI 并指定所需的“EventMask”,可以仅接收特定事件。

我的解决方案是为不同的事件类型创建不同的连接。


-2
投票

我在读取数据时也遇到了问题。我必须为它创建一个单独的线程(一个 Go 例程)并通过通道发送结果,但后来我意识到 读取本身会阻塞客户端路由,因为它等待结束(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)
© www.soinside.com 2019 - 2024. All rights reserved.