持久化PHP套接字的并发使用

8

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


编辑

我是这样使用套接字的:

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

每个PHP线程将共享相同的持久套接字


你能提供一个代码示例帮助我更好地理解你所做的事情吗? - Michel Feldheim
你可以创建尽你的带宽/内存所允许的数量,我想…… - crush
你是如何在线程之间共享套接字的?使用 pthreads 吗? - glomad
我添加了更多关于我如何使用它的细节。 - nathanjosiah
这是我第一次看到这个函数。你能提供这个函数的文档链接吗? - Michel Feldheim
@MichelFeldheim http://us3.php.net/pfsockopen - nathanjosiah
1个回答

26

fsockopen的限制在于系统内核设置中定义的最大打开文件描述符数量。如果pfsockopen实现良好,它应该只使用一个单一的套接字连接,也就是每个PHP进程只有一个文件描述符

你需要测试一下。

例如:

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

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

在Web浏览器中打开并重新加载页面数次 - 每次使用相同的套接字连接时应该看到相同的ID。

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

  • MinSpareServers (≤ npConnections)
  • MaxSpareServers(≥ npConnections)
  • MaxRequestsPerChild(tMax)

当达到MaxRequestsPerChild时,该进程将终止,该子进程上的持久连接也将终止。

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

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

PHP-FPM

  • pm.min_spare_servers(≤ npConnections)
  • pm.max_spare_servers(≥ npConnections)
  • pm.max_requests(tMax)

FastCGI

  • PHP_FCGI_CHILDREN(= npConnections)
  • PHP_FCGI_MAX_REQUESTS(tMax)

在所有配置中,持久连接的最大生存时间(由该进程处理的请求数)为tMax,并发持久连接的最大数量为npConnections

在命令行(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

3
哇,这是一个非常详尽和格式良好的解释。我希望答案基本上就是这样,但我对我的测试结果不确定。谢谢! - nathanjosiah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接