Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1938036
  • 博文数量: 219
  • 博客积分: 8963
  • 博客等级: 中将
  • 技术积分: 2125
  • 用 户 组: 普通用户
  • 注册时间: 2005-10-19 12:48
个人简介

文章分类

全部博文(219)

文章存档

2021年(1)

2020年(3)

2015年(4)

2014年(5)

2012年(7)

2011年(37)

2010年(40)

2009年(22)

2008年(17)

2007年(48)

2006年(31)

2005年(4)

分类: 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以上的心跳。

 

这两句的问题就是顺序,应该先存心跳表,再发心跳。一般系统负载不高时,这两句代码不会有问题,客户端的响应再快,也是网张层的响应,有时延。但在负载高时,有可能在发送完数据后,线程被切换。线程被切换回来时,客户端的响应先到达并被处理了。导致存入心跳表的会话不会再被删除了,待超时时被断开。

 

问题就是这么简单。

阅读(1006) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~