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]