我偶尔会遇到这个问题。 我们有一个使用boost :: asio实现的http客户端和一个处理连接/请求超时的deadline_timer。
async_connect
被调用。 deadline_timer以超时120秒启动。deadline_timer
回调在120秒后被调用,并明确关闭连接。async_connect_callback
调用boost::system::errc::operation_canceled
,此处我也看到计时器已过期。问题:
答案 0 :(得分:2)
没有你的代码,很难说一些真正有用的东西。我建议你将代码降低到暴露问题的最小可行示例。
- 有没有办法调查为什么没有调用async_connect回调来表示成功建立连接?
醇>
您可能会受益于Handler Tracking。启用后,您可以非常全面地了解哪些操作处于待处理状态以及哪些完成处理程序(未)被调用。
示例如下:
@asio|1298160085.070638|0*1|signal_set@0x7fff50528f40.async_wait
@asio|1298160085.070888|0*2|socket@0x7fff50528f60.async_accept
@asio|1298160085.070913|0|resolver@0x7fff50528e28.cancel
@asio|1298160118.075438|>2|ec=asio.system:0
@asio|1298160118.075472|2*3|socket@0xb39048.async_receive
@asio|1298160118.075507|2*4|socket@0x7fff50528f60.async_accept
@asio|1298160118.075527|<2|
@asio|1298160118.075540|>3|ec=asio.system:0,bytes_transferred=122
@asio|1298160118.075731|3*5|socket@0xb39048.async_send
@asio|1298160118.075778|<3|
@asio|1298160118.075793|>5|ec=asio.system:0,bytes_transferred=156
@asio|1298160118.075831|5|socket@0xb39048.close
@asio|1298160118.075855|<5|
@asio|1298160122.827317|>1|ec=asio.system:0,signal_number=2
@asio|1298160122.827333|1|socket@0x7fff50528f60.close
@asio|1298160122.827359|<1|
@asio|1298160122.827370|>4|ec=asio.system:125
@asio|1298160122.827378|<4|
@asio|1298160122.827394|0|signal_set@0x7fff50528f40.cancel
请注意,Asio附带了一个perl脚本,可以从中生成graphviz图:
~/custom/boost/libs/asio/tools/handlerviz.pl /tmp/raw.log | dot -Tpng -o q.png
- io_service队列是否可能被重载?
醇>
只有你这样编程。通常的模式是发布到io_service
的所有任务都应该是非阻塞且短暂的。如果是这样,您应该能够在1个线程上复用严重的IO负载没问题。
如果是这样,是什么原因解释了由于超时而被调用的async_connect_callback?
这是设计服务对象(在您的情况下,套接字)被关闭(甚至被破坏)。文档说在这种情况下所有挂起的异步操作都被取消了,完成处理程序将使用ec = 125(boost::asio::error::operation_abored
)来解雇,就像你说的那样。
如果重要的话,该程序还使用40个线程的线程池。
呃。好多啊。为什么是这样?你真的有40个逻辑CPU核心吗?您是否使用该服务不仅仅是IO任务?在后一种情况下,我强烈怀疑问题在于您“滥用”IO队列以进行长时间运行或(上帝禁止)阻止任务,这意味着IO任务可以缺乏。
这似乎不太可能,但是在存在链的情况下可能性增加,特别是如果链参与这种阻断操作。在这种情况下,整个池在逻辑上对于链上的每个操作都是1个单线程。