XMemcached的一个严重BUG

泰山在线的周利朋友对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,我将及时修复和反馈。

文章转自庄周梦蝶  ,原文发布时间2009-09-27

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Shiro提供的CacheManager将XMemcached集成到Shiro中。 首先,在pom.xml中添加XMemcached和Shiro的依赖,例如: ``` <dependency> <groupId>com.googlecode.xmemcached</groupId> <artifactId>xmemcached</artifactId> <version>2.4.6</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.7.1</version> </dependency> ``` 然后,在Shiro的配置文件中配置CacheManager,例如: ``` <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> <property name="cacheManagerConfigFile" value="classpath:ehcache.xml" /> </bean> ``` 这里使用了EhCacheManager,但可以将其替换为XMemcachedCacheManager。需要自己实现XMemcachedCacheManager类,例如: ``` public class XMemcachedCacheManager implements CacheManager { private MemcachedClient memcachedClient; public XMemcachedCacheManager(String servers) { try { memcachedClient = new XMemcachedClient(servers); } catch (IOException e) { throw new RuntimeException(e); } } @Override public <K, V> Cache<K, V> getCache(String name) throws CacheException { return new XMemcachedCache<>(memcachedClient, name); } @Override public void destroy() throws Exception { memcachedClient.shutdown(); } } ``` 最后,在Shiro的配置文件中使用XMemcachedCacheManager,例如: ``` <bean id="cacheManager" class="com.example.XMemcachedCacheManager"> <constructor-arg value="localhost:11211" /> </bean> ``` 这里使用了本地的XMemcached服务器,可以根据实际情况修改。配置完毕后,就可以在Shiro中使用XMemcached作为缓存了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值