Jan10

【原创】PHP下memcached故障一例小记

Author: leeon  Click: 8344   Comments: 1 Category: php  Tag: php,memcached,set

今天在对PHP应用程序增加缓存时,发现很容易造成set数据失败的情况,打印错误日志显示为:SERVER HAS FAILED AND IS DISABLED UNTIL TIMED RETRY

在csdn的一篇博文中有一些分析:http://blog.csdn.net/tankles/article/details/7208988

但这个分析与php场景不一样,当memcached重启后,笔者发现在php-fpm的场景下最好也重启下php-fpm,要不然会导致php-fpm的进程在调用memcached模块的set方法时认为memcached是失败的。这里的原因我想应该和memcached的长连接在php-fpm进程下的机制有关,当memcached重启后,php-fpm的长连接状态已经非正常,除非php-fpm自然退出,要不然始终会保留错误的连接资源,导致set和get的失败。笔者发现此问题也同样存在于redis的长连接中。

Sep4

【原创】PHP中Sphinx长连接分析

Author: leeon  Click: 6702   Comments: 1 Category: php  Tag: sphinx.php,长连接,持久连接

SphinxClient::open

(PECL sphinx >= 1.0.3)

SphinxClient::open建立到搜索服务端的持久连接

说明

public bool SphinxClient::open ( void )

建立到搜索服务端的持久连接.

参数

此函数没有参数。

返回值

成功时返回 TRUE, 或者在失败时返回 FALSE

今日在做PHP系统代码优化时,对sphinx的长连接做了一些分析发现php的sphinx api并不是我们想象中的那样会在php-fpm的fastcgi状态下一直与sphinx的searchd进程保持长连接,sphinx的api接口中open()方法仅仅提供了在一次会话请求中保证多个sphinx调用在单个php进程中是共用一个sphinx tcp连接通道,当php解释运行完,与sphinx的连接也会自动断开,而不是保持连接状态。

这篇帖子也佐证了楼主的这个想法:http://sphinxsearch.com/forum/view.html?id=7200

> So it seems that the definition of 'persistent connection' in Sphinx is different from
> persistent MySql connections when using a PhP API : the persistence is only across
> multiple calls *in the same php request execution* and not persistence within the client

> process i.e. across multiple php requests.


我们可以做一个这样的实验来证明我的观点:

给php增加sphinx.so扩展,然后写如下测试代码:

[code="php"]
$s = new SphinxClient();

var_dump($s);
$s->setServer('192.168.1.108','9312');
//$s->open();
var_dump($s->query('abxxxx'));
var_dump($s->query('abxxxx'));
[/code]

注意这里$s->open()先屏蔽,然后我们在cli状态下利用strace命令跟踪执行此php脚本,收集系统调用信息会发现:

在系统调用中出现了两次connect到192.168.1.108的请求。也就是说在没调用open方法的时候,在同一个php运行时中会导致两次对sphinx产生的tcp请求。

[code="plain"]
611 fcntl64(3, F_SETFL, O_RDONLY|O_NONBLOCK) = 0
612 connect(3, {sa_family=AF_INET, sin_port=htons(9312), sin_addr=inet_addr("192.168.1.108")}, 16) = -1 EINPROGRESS (Operation now in progress)
613 select(4, NULL, [3], NULL, {60, 0}) = 1 (out [3], left {59, 999996})
614 fcntl64(3, F_SETFL, O_RDONLY) = 0
615 send(3, "\0\0\0\1", 4, MSG_NOSIGNAL) = 4
616 recv(3, "\0\0\0\1", 4, 0) = 4
617 send(3, "\0\0\1\31\0\0\0\224\0\0\0\0\0\0\0\1", 16, MSG_NOSIGNAL) = 16
618 send(3, "\0\0\0\0\0\0\0\24\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\6abxx"..., 140, MSG_NOSIGNAL) = 140
619 recv(3, "\0\0\1\31\0\0\0`", 8, 0) = 8
620 recv(3, "\0\0\0\0\0\0\0\2\0\0\0\5title\0\0\0\4text\0\0\0\2\0\0\0"..., 96, 0) = 96
621 close(3)
。。。。。。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。。。。。
756 socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
757 fcntl64(3, F_SETFL, O_RDONLY|O_NONBLOCK) = 0
758 connect(3, {sa_family=AF_INET, sin_port=htons(9312), sin_addr=inet_addr("192.168.1.108")}, 16) = -1 EINPROGRESS (Operation now in progress)
759 select(4, NULL, [3], NULL, {60, 0}) = 1 (out [3], left {59, 999997})
760 fcntl64(3, F_SETFL, O_RDONLY) = 0
761 send(3, "\0\0\0\1", 4, MSG_NOSIGNAL) = 4
762 recv(3, "\0\0\0\1", 4, 0) = 4
763 send(3, "\0\0\1\31\0\0\0\224\0\0\0\0\0\0\0\1", 16, MSG_NOSIGNAL) = 16
764 send(3, "\0\0\0\0\0\0\0\24\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\6abxx"..., 140, MSG_NOSIGNAL) = 140
765 recv(3, "\0\0\1\31\0\0\0`", 8, 0) = 8
766 recv(3, "\0\0\0\0\0\0\0\2\0\0\0\5title\0\0\0\4text\0\0\0\2\0\0\0"..., 96, 0) = 96
767 close(3) = 0
768 write(1, "array(9) {\n", 11array(9) {


[/code]

然后我们取消open调用的注释,继续strace,会发现这时候依然是连续调用两次query方法,但在第一次query调用后api不会立即close掉tcp连接,而是继续给到第二次query调用使用。

[code="plain"]
611 fcntl64(3, F_SETFL, O_RDONLY|O_NONBLOCK) = 0
612 connect(3, {sa_family=AF_INET, sin_port=htons(9312), sin_addr=inet_addr("192.168.1.108")}, 16) = -1 EINPROGRESS (Operation now in progress)
613 select(4, NULL, [3], NULL, {60, 0}) = 1 (out [3], left {59, 999996})
614 fcntl64(3, F_SETFL, O_RDONLY) = 0
615 send(3, "\0\0\0\1", 4, MSG_NOSIGNAL) = 4
616 recv(3, "\0\0\0\1", 4, 0) = 4
617 send(3, "\0\4\0\0\0\0\0\4\0\0\0\1", 12, MSG_NOSIGNAL) = 12
618 select(4, [3], NULL, [3], {0, 0}) = 0 (Timeout)
619 send(3, "\0\0\1\31\0\0\0\224\0\0\0\0\0\0\0\1", 16, MSG_NOSIGNAL) = 16
620 send(3, "\0\0\0\0\0\0\0\24\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\6abxx"..., 140, MSG_NOSIGNAL) = 140
621 recv(3, "\0\0\1\31\0\0\0`", 8, 0) = 8
622 recv(3, "\0\0\0\0\0\0\0\2\0\0\0\5title\0\0\0\4text\0\0\0\2\0\0\0"..., 96, 0) = 96
623 write(1, "array(9) {\n", 11array(9) {
624 ) = 11
[/code]

Apr29

【原创】在虚拟机环境下使用xdebug注意事项

Author: leeon  Click: 6282   Comments: 0 Category: php  Tag: php,xdebug,vmware,zend studio,zend

此文主要记录在虚拟机xdebug环境下如何解决宿主机zendstudio与xdebug通信的问题,从而根本坚决在调试界面出现57%进度条的问题:

问题现象:zend studio xdebug 57% waiting for xdebug session

作者本人的开发环境通常是windows宿主机器+vmare Linux虚拟机,通过linux的samba功能将虚拟机下的目录共享给windows做磁盘映射,这样的开发环境可以快速的在windows下实现完整的Linux代码调试环境。

今日在虚拟机下给php装xdebug来调试代码时,按照网上的步骤对xdebug做了配置,因为我的虚拟机环境的网络是走NAT的。

linux虚拟机的网段是192.168.2.0/255.255.255.0 ,网关为192.168.2.2.

windows宿主机器的网段是192.168.1.0/255.255.255.0

在windows下浏览器访问虚拟机下的http服务时都是通过vmare 的nat虚拟网卡转发过去,此网卡绑定的p为192.168.2.1。那么问题就来了,虚拟机下获取到的来路请求ip都是192.168.2.1,获取到xdebug的调试请求后转发信息给zend studio时网络却受阻了。我在设置的xdebug端口号是19000.如下如所示:

可以从图中看到我们的请求在发送给192.168.2.1 的19000端口时,但是这是卡住的原因是syn_sent的过程网络不通,导致php无法连接到windows宿主机下的zend studio。只要问题定位到就好办了,最快的解决方法就是开启iptables的端口转发,将发送到192.168.2.1 端口19000的数据全部转发给宿主机IP:192.168.1.105。

我们用root配置如下iptabless规则:

iptables -t nat -A OUTPUT -p tcp -d 192.168.2.1 --dport 19000 -j DNAT --to 192.168.1.105:19000

这样我们的zend studio就可以轻松收到php发来的xdebug调试数据了。

用NAT网络模式的虚拟环境比较蛋疼,如果换成桥接模式让宿主机和虚拟机同一个网段,那么问题迎刃而解。


Feb20

【原创】PHP简单验证码实现代码示例

Author: leeon  Click: 5473   Comments: 0 Category: php  Tag: php,captcha,valid

最近无聊没事做,开始做一些php的分享,代码都比较简单,但比较实用。

这是四年前写的,几行代码实现四位随机数字的php验证码功能。

[code="php"]
session_start();
header("Content-type: image/jpeg");
$img = imagecreate(50,20);
$white = imagecolorallocate($img,211,213,193);
imagefill($img,0,0,$white);
for($i=0;$i<4;$i++){
$r[$i] = rand(0,9);
}
$_SESSION['valid'] = implode("",$r); //在这里写入到session可做后期验证
for($i=0;$i<4;$i++){

if(rand(0,9)%2==0){
imagechar($img,5,($i+1)*8,4,$r[$i],imagecolorallocate($img,rand(0,150),rand(0,150),rand(0,150)));
}else{
imagechar($img,5,($i+1)*8,2,$r[$i],imagecolorallocate($img,rand(0,150),rand(0,150),rand(0,150)));
}

}
imagejpeg($img);
[/code]

分类

标签

归档

最新评论

Abyss在00:04:28评论了
Linux中ramdisk,tmpfs,ramfs的介绍与性能测试
shallwe99在10:21:17评论了
【原创】如何在微信小程序开发中正确的使用vant ui组件
默一在09:04:53评论了
Berkeley DB 由浅入深【转自架构师杨建】
Memory在14:09:22评论了
【原创】最佳PHP框架选择(phalcon,yaf,laravel,thinkphp,yii)
leo在17:57:04评论了
shell中使用while循环ssh的注意事项

我看过的书

链接

其他

访问本站种子 本站平均热度:8823 c° 本站链接数:1 个 本站标签数:464 个 本站被评论次数:94 次