庄周梦蝶

生活、程序、未来
   :: 首页 ::  ::  :: 聚合  :: 管理

XMemcached的一个严重BUG

Posted on 2009-09-27 23:29 dennis 阅读(3367) 评论(6)  编辑  收藏 所属分类: javamy open-source
    泰山在线的周利朋友对xmemcached做了很多测试,他发现了一个比较严重的BUG,在linux平台的重连机制有时候会失效。表现的现象是这样,正常连接上memcached之后,kill掉其中的一台memcched server,xmemcached会开始自动重连这台server直到连接成功,然而事情没有像预想的那样,现象是有时候可以重连成功,有时候却没有,如果设置了connectionPoolSize,有时候建立的连接数达到connectionPoolSize,有时候却没有。他还向我描述了那时候的netstat观察到的网络情况,有比较多CLOSE_WAIT存在,这个显然是由于memcached主动断开,xmemcached被动进入CLOSE_WAIT,但是没有发送FIN的情况,如果有发送FIN那应该进入LAST_ACK而不是停留在CLOSE_WAIT。因此反应的第一个问题是xmemcached没有在接到memcached断开之后主动关闭socket发送FIN。检查代码发现其实是有这个逻辑,但是nio的channel关闭有个隐蔽的问题,就是在SelectionKey.cancel之后还需要调用select才能真正地关闭socket,这里会有个延迟,另外,为了防止CLOSE_WAIT现象的再次发生,设置SO_LINGER选项强制关闭也是必须的。做了这两个修改后,build了一个临时版本请周利朋友帮忙测试,重连失败的情况有所减轻,但是仍然会发生。因此根本的问题不在于CLOSE_WAIT的处理上,通过检查代码发现了下面这段代码:
if(!future.isDone()&&!future.get(DEFAULT_CONNECTION_TIMEOUT,TimeUnit.MILLISECONDS){
  
}
else{
   connected
=true;
}

   可能你已经发现问题在哪。这段代码的意图是通过future.get阻塞等待连接成功或者失败,如果失败做一些处理,如果成功将connected设置为true。这里判断失败有两个条件,future.isDone为false,并且future.get也返回false才认为失败,问题恰恰出在这里,因为future.isDone可能在连接的失败的情况下返回true,而这段逻辑将这种情况误判为连接成功,导致重试的请求被取消。修改很简单,将future.isDone这个条件去掉即可。
    回想起来,我也忘了当初为什么加上这个条件,这里感谢下周利的帮助,并且向使用xmemcached的朋友们提个醒。这个问题在win32平台上不会出现(比较诡异,估计跟并发有关),在linux平台出现的几率比较大,预计在10月份发布的1.2.0-stable中修正,这个stable版主要工作是修复BUG。欢迎更多朋友反馈问题和BUG,我将及时修复和反馈。


评论

# re: XMemcached的一个严重BUG  回复  更多评论   

2009-09-27 23:50 by 周利
dennis这么快速、负责的解决了问题,我很敬佩!

# re: XMemcached的一个严重BUG  回复  更多评论   

2009-09-28 08:52 by bsli123@hotmail.com
希望XMemcached 能保持简洁实用的功能,不要引入太多花哨的东西,正像Memcached一样简洁

# re: XMemcached的一个严重BUG  回复  更多评论   

2009-09-28 09:53 by dennis
@bsli123@hotmail.com
谢谢你的建议。xmemcached发展到现在,很多功能其实都是被动添加的,比如连接池是在用户发现高并发下单连接的nio很容易超时,比如kestrel的支持是有用户拿xmemcached去连接kestrel,所以就xmemcached本身不会主动去添加一些花哨的东西,一个简单的类库也不能承担太多责任。

# re: XMemcached的一个严重BUG  回复  更多评论   

2009-09-28 16:13 by bsli123@hotmail.com
向你请教一个问题,memecache缓存单个对象大小可有什么限制?

# re: XMemcached的一个严重BUG  回复  更多评论   

2009-09-28 16:48 by dennis
@bsli123@hotmail.com
允许的最大大小是1M。

# re: XMemcached的一个严重BUG  回复  更多评论   

2016-05-17 11:16 by wei.huang
非常感谢作者提供这么好的工具,在使用的过程中遇到一些问题?
1、使用连接池后,当一个节点断开连接后会一直尝试连接并报出connect refused 异常?是因为有重试机制吗?
2、动态添加节点addserver时当节点服务通信异常也会抛出connect refused 异常,并一直重试?

麻烦作者提供解决思路,非常感谢

只有注册用户登录后才能发表评论。


网站导航: