PHP mc-client 自动重连的奥秘

我们知道memcache的PHP客户端在连接mc后,如果中间memcached宕掉了,你们重启之后,mc-client会自动连接到server的,这是如何做到的呢?

先写一个test脚本:

<?php
$mc
= new Memcache
();
$mc->connect("10.10.10.10",11211
);

while(1){
$ret = $mc->set("a","a"
);
if(
$ret
) {
echo
"okn"
;
} else {
echo
"failn"
;
}
sleep(1
);
}

?>

启动脚本后,先宕掉memcached,再启动memcached:

                                   间隔时间
第一次失败的时间: 1240491343.709920
第一次重连:      1240491358.751046 15s
第二次重连:      1240491373.790693 15s
第三次重连:      1240491388.829329 15s
第四次重连:      1240491403.869810 15s

结论: mc client 失败后,如果没有主动重连,在15s后再使用该连接,将尝试重连,在15s内根本就不做尝试重连的动作,即使服务器15s内
又恢复正常服务,mc client也是不知道的

——————————————-

关于pconnect的研究:

先写一个test脚本:

<?php
$mc
= new Memcache();
while(
1){
$mc->pconnect("10.55.38.18",11211);
$ret = $mc->set("a","a");
if(
$ret) {
echo
"okn";
} else {
echo
"failn";
}
sleep(1);
}
?>

1. 虽然pconnect是针对apache类程序开发的,但是命令行程序里有相同的效果
2. 虽然$mc->pconnect("10.55.38.18",11211);是写在了循环里面,但是通过tcpdump发现,并没有每次都重连mc
3. 虽然好像每次都重连,其实都还是完全有connect里的机制来控制了,就是说循环里面的pconnect与写到循环外面没有任何的区别
4. 如果把里面的pconnect 换成connect,则效果就和我们想象的一样了,这样,不管服务器端是否有异常,每次都是真正的连接

程序在$mc->pconnect("10.55.38.18",11211);时报的两种错误:
第一种:Warning: Memcache::pconnect(): Can’t connect to 10.55.38.18:11211, Unknown error (0) in /usr/home/junjie2/testmc.php on line 4

第二种:PHP Warning:  Memcache::pconnect(): Can’t connect to 10.55.38.18:11211, Connection refused (111) in /usr/home/junjie2/testmc.php on line 4

前者是因为并没有真正去连接,只是发现连接不可用(已关闭)就直接返回错误了
后者是第一次失败的15s之后,就尝试做一次真正的重新连接,因为这是memcached还没有重启,就返回了 Connection refused,这样下次pconnect,又接着返回第一种错误,直到又过15s

php的memcahce-2.2.4 中文件 php_memcache.h 中有如下定义

#define MMC_DEFAULT_RETRY 15                             /* retry failed server after x seconds */

即:  15s内是不做真正的连接的。

注意: memcache客户端默认设置的超时时间为1s, 极容易超时的,所以你要知道,当超时后,客户端会主动关闭连接的,因为它以为服务器down了,然后就是15s内的操作统统返回失败。

如何避免这种问题呢?

办法一: 在第一个测试脚本中,使用了connect,而不是pconnect, 连接操作是在循环体外的;如果connect(注意不是pconnect)发生在循环体内就能及时发现连接已有效了,就不需要等待15s了,当然,这样的话,每次都是真实的重新连接了,而且特别需要注意的是,如果这样的话,close()操作也一定要写在循环体里面,否则你将创建n多连接,知道不允许你在连接了。

办法二: 使用addServer的方式: bool Memcache::addServer     ( string $host    [, int $port = 11211    [, bool $persistent    [, int $weight    [, int $timeout    [, int $retry_interval    [, bool $status    [, callback $failure_callback    [, int $timeoutms   ]]]]]]]] )

    将$retry_interva 设置为0,这样就每次都重新连接了。


留下评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据