起因是项目向华为云 OBS 请求视频, 偶现题目中的异常;如果等一段时间(30s),就可以正常读取到视频。
原因是 OBS SDK 底层用的 Okhttp 连接池,而 Okhttp 的 GitHub 上也有相关 issue:
-
服务器在返回数据后就直接关闭 TCP 连接,而客户端(项目应用)却将连接放入连接池重复使用;
-
当下次请求复用时,连接已经被关闭,就读取不到返回值,报上述异常。
-
如果等待一段时间,等连接池杀掉闲置连接(闲置存活时长 30s),那下次请求就会重新建立一个连接,就可以正常拉到视频。
解决的方法很多,有生硬的,有灵活的;可以改上层代码,可以动二方库的包。
但是因为我们明明所有环境都连一个 OBS 服务器,但只有一个环境出现上述问题。
最后发现根本原因是:出问题的环境连的是代理服务器,代理服务器没有开启 keepalive。
后面讲一下排查过程和可以解决的手段。
急需解决方案的,直接看解决手段吧。
如果查看日志的话,标题的异常会被 Okhttp 用 IOException 封装一下连接信息抛出来,最后被华为云 OBS SDK 再包一层
ObsException: OBS servcie Error Message
。
所以第一步,找到根本原因是
Caused by: java.io.EOFException: \n not found: limit=0 content=…
。