在公司排查问题时遇到一个很奇怪的case。
网站前端业务逻辑用Jsp写的,后端数据库用C写的。JSP与数据库之间采取socket通信,连接为长连接。
有客户反映,打开网页后没有查到数据,经过排查JSP前端的日志里记录了用户的这次请求,而后台数据库的访问日志里却没有这个请求记录。
通过检查JSP业务端的日志发现,这种情况出现的很少,一个月中只有几天出现,一天也就出现几次,而且在JSP业务端的日志中都有记录,但是在后台数据库中没有记录,这条查询请求莫名奇妙的消失了。
JSP业务端的记录了,该请求到达的时间,查询条件(类似于sql语句),以及从后台数据库的返回结果,奇怪的是日志中显示从后台数据库的返回结果全部为0,但是后台数据库是正常情况下是不会返回全为0的结果的(除非有bug)。
那么究竟是JSP的程序写错了?还是后台数据库模块出现了问题呢?
JSP端的代码(伪java代码)
try { // code ... bool valid = isConnectionValid(socket); if (valid) { in = socket.getInputStream(); out = socket.getOutputStream(); out.write(request); byte[] data = new byte[HeadLength]; in.read(data); Log(data); // log data } } catch(Exception e) { Log.warning(e); }
首先会判断该连接是否可用,如果是可用的那么发送请求头,发送之后new一个接受体,然后等待后台数据库的相应,接收到数据后将接收到的内容记录到日志中。
看上去没什么问题,如果网络出现异常那么sokcet抛出Exception。
由于本人是写C的,由于C语言没有异常机制,所以必须通过检查返回值来判断函数是否成功执行。所以我查了JDK中的read。
public int read(byte[] b) throws IOException 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。以整数形式返回实际读取的字节数。 在输入数据可用、检测到文件末尾或者抛出异常前,此方法一直阻塞。 如果 b 的长度为 0,则不读取任何字节并返回 0;否则,尝试读取至少一个字节。 如果因为流位于文件末尾而没有可用的字节,则返回值 -1; 否则,至少读取一个字节并将其存储在 b 中。
发现read其实是可以返回0或者-1的,本case b的长度不为0,那么什么叫流位于文件末尾而没有可用的字节呢??
对于文件,读到文件的末尾没有可用字节。对于socket什么情况下会到达末尾呢?
其实这个比较简单,当服务器端写完数据后会close socket,这便是socket的结束标记。
out = socket.getOutputStream();
out.write(buffer);
out.close(); // 流结束标记
也是说引发这个查询消失的原因是:客户端连接服务器后,服务器没有返回任何数据,就关闭了连接,而客户端的代码没有检查read的返回值,就进行了后面的操作。
由于客户端事先检查了连接是可用的才发送的请求,所以在read之后没有检查返回值。而java把new出来的data默认填0,因此客户端还以为服务器返回了0.
那么服务器(后台数据库)为什么会没有返回数据就关闭连接呢?
主要是长连接的缘故,对于不活动的长连接,当不活动的时间到达一定的阈值后,服务器机会关闭这些连接,这就存在了一个时间差,服务找到一个长时间不活动的长连接,准备关闭这个长连接,os在此时进行了一次进程调度,然后客户的请求来了,连接到了这个即将关闭的连接,并且发送了数据,之后服务器进程休眠结束,关闭了此链接。
而客户端发现sokcet到了末尾,于是返回-1,并且将data的内容打印出来,data初始化为0,因此log中有全为0的记录,但是服务器却没有这条记录。这就是请求的全过程。
客户端 服务器 准备关闭socket 测试socket是否存活(ok) 连接 ok 发送数据 ok 长连接超时,关闭socket 没有检测read返回值,数组中 的数据默认为0
服务器在关闭sokcet之前不会再次检查这个socket是否又有新的连接,这种情形其实是很难出现的,因为要恰好再关闭sokcet之间进行一次调度,而且恰好一个请求过来了,这也解释了为什么这种现象会很少出现。
通过这个case,有几点值得我们注意:
评论加载中...
|
Copyright@ 2011-2017 版权所有:大连仟亿科技有限公司 辽ICP备11013762-1号 google网站地图 百度网站地图 网站地图
公司地址:大连市沙河口区中山路692号辰熙星海国际2215 客服电话:0411-39943997 QQ:2088827823 42286563
法律声明:未经许可,任何模仿本站模板、转载本站内容等行为者,本站保留追究其法律责任的权利! 隐私权政策声明