无
分类: Java
2012-03-17 12:31:39
前两天做程序性能测试,出现了与时间有关的BUG,写在这里,与大家共同学习。
场景是这样的: 在测试中,是一个SOCKET服务器端,一个SOCKET客户端。双方保持长连接,并且规定每5分钟由服务器端发应用层保活。客户端在收到保活消息后发送一个响应,服务器发保活到收响应的时间不得大于20秒,否则则认为连接异常,关闭连接。
服务器实现是在发送保活后,把客户端ID存入保活表,记录当前时间。服务器在收到保活响应时,把保活表的客户端ID删除。客户端只要收到保活马上就给响应。
下面是服务器端发送数据和存到心跳表的代码。就是这两句,导致了问题。
session.write(BaseFactory.getACT());
this.heartbeatSessionList.put(id, session);
先介绍一下系统环境: 系统的水位很高,后台的线程池切换非常频繁,后台线程池是32线程,本机有16CPU。客户端的响应也非常快,在1ms以下级别。服务器端一秒要发送2000以上的心跳。
这两句的问题就是顺序,应该先存心跳表,再发心跳。一般系统负载不高时,这两句代码不会有问题,客户端的响应再快,也是网张层的响应,有时延。但在负载高时,有可能在发送完数据后,线程被切换。线程被切换回来时,客户端的响应先到达并被处理了。导致存入心跳表的会话不会再被删除了,待超时时被断开。
问题就是这么简单。