xmemcached timeout

小乞丐 发布于 2015/03/26 15:09
阅读 4K+
收藏 0

各位好!最近在弄memcached2.0,客户端采用xmemcached,但是会遇到读取数据超时的情况!

采用magent代理;客户端连接magent服务;


初始化方法:

public void init() {
/** 设置与缓存服务器的连接池 */
MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddressMap(serverAddress));
try {
//启用failure模式。
builder.setFailureMode(true);
builder.setSessionLocator(new KetamaMemcachedSessionLocator());
builder.setConnectionPoolSize(poolSize);
builder.setHealSessionInterval(healConnectionInterval);
mcc = builder.build();
if(mcc!=null){
mcc.setConnectTimeout(soTimeout);
mcc.setOpTimeout(soTimeout);
}
log.info("Memcache initialization successful!"+serverAddress);
} catch (IOException e) {
log.error("初始化memcache连接失败:" + e.getLocalizedMessage(), e);
}
}



/**
* 根据指定的关键字获取对象. 内部测试方法, 准备删除.

* @param key
* @return
* @throws MemcachedException
* @throws InterruptedException
* @throws TimeoutException
*/
public Object get(String key) throws Exception {
try {
return mcc.get(key);
} catch (TimeoutException e) {
String message = "读取缓存超时key="+key;
log.error(message, e);
throw new Exception(message, e);
} catch (InterruptedException e) {
String message = "读取缓存被打断key="+key;
log.error(message, e);
throw new Exception(message, e);
} catch (MemcachedException e) {
String message = "读取缓存异常key="+key;
log.error(message, e);
throw new Exception(message, e);
}


}

错误描述: 在本地循环测试始终不能浮现,在测试环境,c++ 写入缓存后发送消息至 我这边,然后读取指定key,有时候能读取到数据,有时候会不会超时,超时比较频繁;每条数据大小也就只有几k;另外日志会显示客户端4次心跳失败;

java.lang.Exception: 读取缓存超时key=xxxxxx
at com.palmcity.memached.MemcacheManager.get(MemcacheManager.java:410)
at com.palmcity.bus.handler.thrift.ThriftBusArrivalHandler.handler(ThriftBusArrivalHandler.java:48)
at com.palmcity.bus.handler.thrift.ThriftServerImpl.sendCommand(ThriftServerImpl.java:51)
at com.palmcity.bus.servers.ThriftCommandService$Processor$sendCommand.getResult(ThriftCommandService.java:175)
at com.palmcity.bus.servers.ThriftCommandService$Processor$sendCommand.getResult(ThriftCommandService.java:1)
at org.apache.thrift.ProcessFunction.process(ProcessFunction.java:39)
at org.apache.thrift.TBaseProcessor.process(TBaseProcessor.java:39)
at org.apache.thrift.server.TThreadPoolServer$WorkerProcess.run(TThreadPoolServer.java:225)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Caused by: java.util.concurrent.TimeoutException: Timed out(50000 milliseconds) waiting for operation while connected to 192.168.3.101:12000
at net.rubyeye.xmemcached.XMemcachedClient.latchWait(XMemcachedClient.java:2536)
at net.rubyeye.xmemcached.XMemcachedClient.fetch0(XMemcachedClient.java:644)
at net.rubyeye.xmemcached.XMemcachedClient.get0(XMemcachedClient.java:1058)
at net.rubyeye.xmemcached.XMemcachedClient.get(XMemcachedClient.java:1016)
at net.rubyeye.xmemcached.XMemcachedClient.get(XMemcachedClient.java:1027)
at net.rubyeye.xmemcached.XMemcachedClient.get(XMemcachedClient.java:1049)
at com.palmcity.memached.MemcacheManager.get(MemcacheManager.java:406)
... 10 more


java.lang.Exception: 读取缓存超时key=xxxxxx
at com.palmcity.memached.MemcacheManager.get(MemcacheManager.java:410)
at com.palmcity.bus.handler.thrift.ThriftBusArrivalHandler.handler(ThriftBusArrivalHandler.java:48)
at com.palmcity.bus.handler.thrift.ThriftServerImpl.sendCommand(ThriftServerImpl.java:51)
at com.palmcity.bus.servers.ThriftCommandService$Processor$sendCommand.getResult(ThriftCommandService.java:175)
at com.palmcity.bus.servers.ThriftCommandService$Processor$sendCommand.getResult(ThriftCommandService.java:1)
at org.apache.thrift.ProcessFunction.process(ProcessFunction.java:39)
at org.apache.thrift.TBaseProcessor.process(TBaseProcessor.java:39)
at org.apache.thrift.server.TThreadPoolServer$WorkerProcess.run(TThreadPoolServer.java:225)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Caused by: java.util.concurrent.TimeoutException: Timed out(5000 milliseconds) waiting for operation while connected to 192.168.3.101:12000
at net.rubyeye.xmemcached.XMemcachedClient.latchWait(XMemcachedClient.java:2536)
at net.rubyeye.xmemcached.XMemcachedClient.fetch0(XMemcachedClient.java:644)
at net.rubyeye.xmemcached.XMemcachedClient.get0(XMemcachedClient.java:1058)
at net.rubyeye.xmemcached.XMemcachedClient.get(XMemcachedClient.java:1016)
at net.rubyeye.xmemcached.XMemcachedClient.get(XMemcachedClient.java:1027)
at net.rubyeye.xmemcached.XMemcachedClient.get(XMemcachedClient.java:1049)
at com.palmcity.memached.MemcacheManager.get(MemcacheManager.java:406)
... 10 more


5-03-25 19:18:01 [WARN]-[MemcachedHandler.java:246] Session(192.168.3.101:12000) heartbeat fail 4 times,close session and try to heal it
 2015-03-25 19:18:01 [WARN]-[MemcachedConnector.java:360] Client in failure mode,we don't remove session 192.168.3.101:12000

加载中
0
小乞丐
小乞丐

引用来自“dennis_zhuang”的评论

我写的是

mcc.setEnableHeartBeat(false);


xmemcached 默认使用 version 协议做心跳,如果代理中间件不支持就会检测失败,断开连接。

心跳不是必须。他跟重连也没有必然联系。


就我刚刚测试来看,问题似乎已经已经完美解决了,谢谢你哈!

这块的源码看了看,有些看不太明白!在开始连接的时候,对连接失败的放入一个wating队列进行反复延迟从连,失败close,同时在创建一个新的session;当连接超过空闲时间后,又做一个version 协议的心跳检查;只要version协议检查成功,会不会存在连接永远不会关闭,也就是连接池如果最大连接数设置为1000,当某个高峰时刻需求达到了连接创建了1000个,高峰过后,连接并未进行关闭;

dennis_zhuang
dennis_zhuang
xmemcached 是基于 nio 的,连接池通常都不需要设置,默认的单链接配置足够。xmc 的连接池是固定大小,不会自动增加或者减少,没有必要。
0
dennis_zhuang
dennis_zhuang

你确认下 magent 是否支持 version 协议吧。如果不支持,禁用心跳:

mcc.setEnableHeartBeat(false);

0
小乞丐
小乞丐

引用来自“dennis_zhuang”的评论

你确认下 magent 是否支持 version 协议吧。如果不支持,禁用心跳:

mcc.setEnableHeartBeat(false);

@dennis_zhuang

没明白version协议是什么意思? magent版本是0.5。系统是Centos6.0

禁用心跳后还是会出现,超时时间均为默认值;

public void init() {
/** 设置与缓存服务器的连接池 */
MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddressMap(serverAddress));
try {
//启用failure模式。
builder.setFailureMode(true);
builder.setSessionLocator(new KetamaMemcachedSessionLocator());
builder.setConnectionPoolSize(poolSize);
//builder.setEnableHealSession(true);
//builder.setHealSessionInterval(healConnectionInterval);
mcc = builder.build();
/*if(mcc!=null){
mcc.setConnectTimeout(soTimeout);
mcc.setOpTimeout(soTimeout);
}*/
log.info("Memcache initialization successful!"+serverAddress);
} catch (IOException e) {
log.error("初始化memcache连接失败:" + e.getLocalizedMessage(), e);
}
}


小乞丐
小乞丐
如果不使用心跳的话,连接池就没有意义了。memcached 服务挂掉之后,不会自动恢复连接。难道还得重启应用?
小乞丐
小乞丐
不好意思,弄错了。。默认心跳也是开启的/。
0
dennis_zhuang
dennis_zhuang

我写的是

mcc.setEnableHeartBeat(false);


xmemcached 默认使用 version 协议做心跳,如果代理中间件不支持就会检测失败,断开连接。

心跳不是必须。他跟重连也没有必然联系。

0
滔哥
滔哥
不是防火墙问题?
小乞丐
小乞丐
不是哈。
返回顶部
顶部