并发使用一个持久的 PHP 套接字 [英] Concurrent use of a persistent PHP socket

查看:18
本文介绍了并发使用一个持久的 PHP 套接字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

<小时>

编辑

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

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

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

解决方案

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

您必须对此进行测试.

例如

$fd = pfsockopen('173.194.44.24', 80);回声 $fd;

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

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

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

  • MinSpareServers (<= n pConnections)
  • 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 (<= n pConnections)
  • 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交互式 shell # 在网络服务器环境中这相当于一个孩子php >$fd1 = fsockopen('google.de', 80);# 打开非持久连接php >回声 $fd1 ."\n";资源 ID #1php >$fd2 = fsockopen('google.de', 80);# 打开另一个php >回声 $fd2 ."\n";资源 id #2 # 新 fd,新连接php >$pd1 = pfsockopen('google.de', 80);# 持续连接php >回声 $pd1 ."\n";Resource id #3 # 第一个持久化 fdphp >$pd2 = pfsockopen('google.de', 80);php >回声 $pd2 ."\n";Resource id #3 # 使用相同的连接php >exit # 模拟 MaxRequestsPerChild 阈值# php -a交互式外壳php >$pd3 = pfsockopen('google.de', 80);# 持久连接,同一主机php >回声 $pd3 ."\n";Resource id #1 # 资源 id 重用,因为所有旧连接都消失了

编辑

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

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

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

再次在 cli 上模拟:

# php -a交互式外壳php >$pd1 = pfsockopen('127.0.0.1', 80);php >回声 $pd1 ."\n";资源 ID #1php >$pd1 = pfsockopen('127.0.0.1', 80);php >回声 $pd1 ."\n";资源 ID #1(在另一个控制台/etc/init.d/nginx restart 上重新启动我的网络服务器)php >$pd1 = pfsockopen('127.0.0.1', 80);php >回声 $pd1 ."\n";资源 ID #2

I am wanting to use PHP to create a persistent socket connection to a notification service server and I am wondering how many Apache/PHP threads would be able to concurrently use the socket before I have problems. I have done some testing with this but I cannot seem to produce any problems.


Edit

I am using the socket like this:

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

Every PHP thread would share the same persistent socket

解决方案

The limitation with fsockopen is the maximum amount of open file descriptors defined in the systems kernel settings. If pfsockopen is implemented well, it should only use one single socket connection, means only one file descriptor per php process.

You'll have to test this.

e.g.

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

This will output the id of the file descriptor: Resource id #1

Open this in a web browser and reload the page several times - you should see the same id each time you are using the same socket connection.

In a default Apache prefork MPM - mod_php setup you probably are randomly sent to different forked processes which will most likely result in n different ids cycling through, while n depends on your Apache configuration of

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

When you reach MaxRequestsPerChild the process is terminated and the persistent connection on this child as well.

In a Apache Worker MPM or any other fastcgi-capable webserver like Lighttpd or Nginx combined with PHP-FPM or PHP-cgi + fastcgi I am expecting the same behavior, now not caused by the webserver but by the php processes.

In parallel to the apache settings described above, the relevant settings are

PHP-FPM

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

FastCGI

  • PHP_FCGI_CHILDREN (= n pConnections)
  • PHP_FCGI_MAX_REQUESTS (tMax)

In all configurations the maximum lifetime of a persistent connection is (in amount of requests handled by that process) tMax, the max amount of parallel persistent connections n pConnections

Simulating this on the command-line (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

EDIT

Acually I forgot to mention a second limitation. Connections of course can be closed anytime by the server itself. This heavily depends on the server settings and protocol you are using.

Most servers close a connection after n seconds of silence and after x seconds of total connection time.

pfsockopen handles this silently, it simply opens a new connection when the old one is gone.

Simulating this on cli again:

# 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 套接字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆