现场的一套服务端程序是用boost.asio做的。
前几天程序莫名其妙的停了,多亏是主备的,要不然影响会很大。
查看日志:
2016-03-29 21:43:42.876 DEBUG - connection 2014_171 closed
2016-03-29 21:43:42.876 INFO - stop listen on 2014
2016-03-29 21:43:42.878 DEBUG - connection 2014_170 closed
2016-03-29 21:43:42.879 DEBUG - connection 2014_169 closed
2016-03-29 21:43:42.879 DEBUG - connection 2014_168 closed
2016-03-29 21:43:42.879 DEBUG - connection 2014_167 closed
2016-03-29 21:43:42.879 DEBUG - connection 2014_166 closed
2016-03-29 21:43:42.879 DEBUG - connection 2014_165 closed
2016-03-29 21:43:42.880 DEBUG - connection 2014_164 closed
2016-03-29 21:43:42.880 DEBUG - connection 2014_163 closed
2016-03-29 21:43:42.880 DEBUG - connection 2014_162 closed
2016-03-29 21:43:42.880 DEBUG - connection 2014_161 closed
2016-03-29 21:43:42.880 DEBUG - connection 2014_160 closed
2016-03-29 21:43:42.880 DEBUG - connection 2014_159 closed
2016-03-29 21:43:42.885 ERROR - exception: remote_endpoint: Transport endpoint is not connected
最后的exception是问题所在。
google一下,错误应该是来自boost::asio::ip::tcp::socket 调用remote_endpoint()函数失败。
程序逻辑是服务端获取到客户端链接以后,会调用remote_endpoint() 来获取远程地址,
那么返回这个错误的原因在于客户端建立连接以后一瞬间,服务端调用remote_endpoint前,就断开了链接,导致返回失败。
写了一个小程序,模拟再现了这个错误,确认上面的想法。
和现场沟通了一下,造成这个错误的客户端并非是业务处理的客户端,
而是现场的监控扫描程序,会一直扫描各个服务程序的地址和端口,以便确认服务程序在正常运行。
定位了问题和原因,开始修改,查看了boost官方网站说明。
这个io_service的错误会一直向上级返回给四个函数run(), run_one(), poll() or poll_one()。
我们服务端使用run函数。
官方也给出了这个错误的修改建议:
改完之后,模拟异常并验证无问题。