并发使用持久性 PHP 套接字

Posted

技术标签:

【中文标题】并发使用持久性 PHP 套接字【英文标题】:Concurrent use of a persistent PHP socket 【发布时间】:2012-12-25 10:28:20 【问题描述】:

我想使用 php 创建到通知服务服务器的持久套接字连接,我想知道在我遇到问题之前有多少 Apache/PHP 线程能够同时使用该套接字。我已经对此进行了一些测试,但似乎无法产生任何问题。


编辑

我正在使用这样的套接字:

$fh = pfsockopen('127.0.0.1', '1338');
fwrite($fh,$data);

每个 PHP 线程都将共享同一个持久套接字

【问题讨论】:

你能提供一个代码示例来帮助我想象你的工作吗? 您可以创建尽可能多的带宽/内存,我假设... 如何在线程之间共享套接字?线程? 我添加了更多关于我如何使用它的细节。 第一次看到这个功能。你能链接这个文档吗? 【参考方案1】:

fsockopen 的限制是系统内核设置中定义的打开文件描述符的最大数量。如果pfsockopen实现得好,它应该只使用一个socket连接,意味着每个php进程只有一个文件描述符

您必须对此进行测试。

例如

$fd = pfsockopen('173.194.44.24', 80);
echo $fd;

这将输出文件描述符的id:Resource id #1

在网络浏览器中打开它并多次重新加载页面 - 每次使用相同的套接字连接时,您应该会看到相同的 id。

在默认的 Apache prefork MPM - mod_php 设置中,您可能会被随机发送到不同的分叉进程,这很可能会导致 n 个不同的 id 循环通过,而 n 取决于您的 Apache 配置 p>

MinSpareServers ( MaxSpareServers (>= n pConnections) MaxRequestsPerChild (tMax)

当您到达MaxRequestsPerChild 时,该进程将终止,并且此子节点上的持久连接也将终止。

在 Apache Worker MPM 或任何其他支持 fastcgi 的网络服务器(如 Lighttpd 或 nginx)与 PHP-FPM 或 PHP-cgi + fastcgi 结合使用时,我期待相同的行为,现在不是由网络服务器引起,而是由 php 进程引起。

与上述的apache设置并行,相关设置为

PHP-FPM

pm.min_spare_servers ( pm.max_spare_servers (>= n pConnections) pm.max_requests (tMax)

FastCGI

PHP_FCGI_CHILDREN (= n pConnections) PHP_FCGI_MAX_REQUESTS (tMax)

在所有配置中,持久连接的最大生命周期为(以该进程处理的请求数量)tMax,并行持久连接的最大数量n pConnections

在命令行(php-cli)上模拟这个

# php -a
Interactive shell                            # in a webserver environment this is the equivalent of one child

php > $fd1 = fsockopen( 'google.de', 80 );   # open non-persistent connection
php > echo $fd1 . "\n";
Resource id #1
php > $fd2 = fsockopen( 'google.de', 80 );   # open another one
php > echo $fd2 . "\n";
Resource id #2                               # new fd, new connection

php > $pd1 = pfsockopen( 'google.de', 80 );  # persistent connection
php > echo $pd1 . "\n";
Resource id #3                               # first persistent fd
php > $pd2 = pfsockopen( 'google.de', 80 );
php > echo $pd2 . "\n";                        
Resource id #3                               # uses the same connection

php > exit                                   # simulating MaxRequestsPerChild threshold
# php -a
Interactive shell

php > $pd3 = pfsockopen( 'google.de', 80 );  # persistent connection, same host
php > echo $pd3 . "\n";
Resource id #1                               # resource id reused because all old connections are gone

编辑

实际上我忘了提到第二个限制。 当然,服务器本身可以随时关闭连接。 这在很大程度上取决于您使用的服务器设置和协议。

大多数服务器会在n 秒的静默时间和x 秒的总连接时间后关闭连接。

pfsockopen 默默地处理这个问题,它只是在旧连接消失时打开一个新连接。

再次在 cli 上模拟:

# php -a
Interactive shell

php > $pd1 = pfsockopen( '127.0.0.1', 80 );
php > echo $pd1 . "\n";
Resource id #1
php > $pd1 = pfsockopen( '127.0.0.1', 80 );
php > echo $pd1 . "\n";
Resource id #1

(restarting my webserver on the another console /etc/init.d/nginx restart)

php > $pd1 = pfsockopen( '127.0.0.1', 80 );
php > echo $pd1 . "\n";
Resource id #2

【讨论】:

哇,这是一个非常彻底且格式正确的解释。我希望答案基本上是这样,但我不确定我的测试结果。谢谢!

以上是关于并发使用持久性 PHP 套接字的主要内容,如果未能解决你的问题,请参考以下文章

仅套接字 IO 会话不持久

高并发redis - 持久化备份方案

并发请求事务以防止不需要的持久性

C套接字HTTP 1.1持久连接服务器何时应关闭套接字?

Android 上的持久 HttpURLConnections

带有 socket.io 状态的 UseEffect 钩子在套接字处理程序中不持久