【发布时间】:2011-12-13 05:22:23
【问题描述】:
我的客户端-服务器应用程序有问题。由于我几乎没有理智的想法来解决它,我正在寻求帮助。我现在已经偶然发现了大约三到四次所描述的情况。提供的数据来自上次失败,当时我已打开所有可能的日志记录、消息转储等。
系统说明
1) Client. 在 Windows 下工作。我假设它的工作没有问题(从日志来看)
2) 服务器。 在 Linux (RHEL 5) 下工作。这是我遇到问题的服务器。
3) 两个连接在客户端和服务器之间维护:一个命令和一个数据发送。两者都是异步工作的。两个连接都存在于一个线程和一个 boost::asio::io_service。
4) 要发送的数据 从客户端到服务器是由 '\0' 分隔的消息。
5) 数据负载约为 50 Mb/小时,全天 24 小时。
6) 在服务器端使用boost::asio::async_read_until 和相应的分隔符读取数据
问题
- 两天系统按预期工作
- 第三天18:55 服务器从客户端读取了最后一条消息,然后停止读取它们。日志中没有关于新数据的信息。
- 从18:55 到09:00(14 小时)客户端没有报告错误。所以它成功发送了数据(大约 700 Mb)并且没有出现错误。
- 在08:30 我开始调查一个问题。服务器进程处于活动状态,服务器和客户端之间的连接也处于活动状态。
- 在09:00,我使用gdb 附加到服务器进程。服务器处于睡眠状态,等待来自系统的一些信号。我相信我不小心按了 Ctrl + C 并且可能有一些消息。
- 后来在日志中我发现了类似“系统调用中断”的消息。之后,与客户端的两个连接都被删除了。客户端重新连接,服务器开始正常工作。
- 服务器处理的第一条消息在客户端的时间戳为18:57。因此,在重新开始正常工作后,服务器并没有将所有消息丢弃到09:00,它们被存储在某个地方并在此之后相应地处理它们。
我尝试过的事情
- 上面的模拟场景。当服务器转储所有传入消息时,我编写了一个小脚本,将自己呈现为客户端并将所有消息再次发送回服务器。服务器因out of memory 错误而中断,但不幸的是,这是因为数据负载高(这次约为 3 Gb/小时),而不是因为同样的错误。由于是星期五晚上,我没有时间正确地重复实验。
- 尽管如此,我还是通过 Valgrind 运行服务器来检测可能的内存泄漏。没有发现任何严重的问题(除了服务器由于高负载而被丢弃的事实),没有巨大的内存泄漏。
问题
- 客户端发送而服务器没有得到的这些 700 Mb 数据在哪里?为什么当服务器重新启动连接时它们是持久的并且没有丢失?
- 在我看来,问题与服务器没有收到来自boost::asio::io_service 的消息有关。缓冲区被数据填充,但没有调用读取处理程序。这可能是操作系统方面的问题吗?异步调用可能有问题?如果是这样,如何检查?
- 我可以做些什么来检测问题的根源?正如我所说,我已经没有理智的想法了,而且每个实验的时间成本都很高(大约需要两到三天才能使系统达到所描述的状态),所以我需要尽可能多地对实验进行检查我可以。
如果我能使用任何想法来解决错误,我将不胜感激。
更新:好的,看来错误是在同步write 留在异步客户端-服务器交互中间。由于两个连接都存在于一个线程中,这个同步的write 出于某种原因阻塞了线程,并且命令和数据连接上的所有交互都停止了。因此,我将其更改为异步版本,现在它似乎可以工作了。
【问题讨论】:
-
有趣。周一开始工作时返回更多信息 :)
-
您还检查过丢包、tcp 缓冲区队列大小增长吗?再次测试时跟踪它们会更好
-
@ArunMu 由于我目前几乎没有任何想法,因此获得更明智的信息会有点困难。不,我没有检查数据包丢失/tcp 缓冲区队列大小的增长。我可以用一些系统工具监控它,还是应该在代码中检查一下?
-
检查 netstat 选项。对于 unix,它是“netstat -S”。对于 linux 它的一些其他选项,您还可以检查 proc 文件系统的 tcp 参数
标签: c++ boost asynchronous client-server boost-asio