在执行多项任务时执行PHP线程

在执行多项任务时执行PHP线程,php,Php,我正在用PHP编写一种代理 此代理将与服务器建立一些连接,如果不需要发送其他命令,则通过每隔一段时间发送一个“ping”数据包来保持连接的打开 客户端应该能够连接到代理,并让它将消息转发到服务器上。在这种情况下,代理将选择一个当前不忙的连接(如果多个客户端已连接且其中一个请求需要一段时间),并使用该非忙连接 我的想法是:使用RabbitMQ作为队列。客户端向RabbitMQ提交消息并等待响应。在服务器端,每个连接都将是它自己的线程,每个线程将不断等待来自RabbitMQ的工作,第一个从Rabbi

我正在用PHP编写一种代理

此代理将与服务器建立一些连接,如果不需要发送其他命令,则通过每隔一段时间发送一个“ping”数据包来保持连接的打开

客户端应该能够连接到代理,并让它将消息转发到服务器上。在这种情况下,代理将选择一个当前不忙的连接(如果多个客户端已连接且其中一个请求需要一段时间),并使用该非忙连接

我的想法是:使用RabbitMQ作为队列。客户端向RabbitMQ提交消息并等待响应。在服务器端,每个连接都将是它自己的线程,每个线程将不断等待来自RabbitMQ的工作,第一个从RabbitMQ获取消息的线程将完成请求。但是在这种情况下,由于连接线程一直在忙着等待工作,如果没有工作,我该如何发送keepalive数据包呢


如果这是一个坏主意,那么如何正确地解决这个问题呢?

从体系结构上讲,线程是解决这个问题的一个很好的方法,因此您肯定以正确的方式思考这个问题。不幸的是,PHP不支持线程!因此,您必须使用进程,而不是通过。(不是我的代码),创建一个新进程来处理每个连接,而不是线程

/**
 * Connection handler
 */
function onConnect( $client ) {
    $pid = pcntl_fork();

    if ($pid == -1) {
         die('could not fork');
    } else if ($pid) {
        // parent process
        return;
    }

    $read = '';
    printf( "[%s] Connected at port %d\n", $client->getAddress(), $client->getPort() );

    while( true ) {
        $read = $client->read();
        if( $read != '' ) {
            $client->send( '[' . date( DATE_RFC822 ) . '] ' . $read  );
        }
        else {
            break;
        }

        if( preg_replace( '/[^a-z]/', '', $read ) == 'exit' ) {
            break;
        }
        if( $read === null ) {
            printf( "[%s] Disconnected\n", $client->getAddress() );
            return false;
        }
        else {
            printf( "[%s] recieved: %s", $client->getAddress(), $read );
        }
    }
    $client->close();
    printf( "[%s] Disconnected\n", $client->getAddress() );

}
require "sock/SocketServer.php";
$server = new \Sock\SocketServer();
$server->init();
$server->setConnectionHandler( 'onConnect' );
$server->listen();
你说你还需要一个线程来发送keepalives。我想说,最简单的解决方案是
pnctl\u fork()
在其他进程繁忙时,再使用一个进程发送keepalives


对于keepalive消息,您可以在forked连接处理程序进程中执行此操作。然后,在连接处理程序进程下面的另一个分叉进程中进行实际工作。

从架构上讲,线程是解决此问题的一个很好的方法,因此您肯定以正确的方式考虑此问题。不幸的是,PHP不支持线程!因此,您必须使用进程,而不是通过。(不是我的代码),创建一个新进程来处理每个连接,而不是线程

/**
 * Connection handler
 */
function onConnect( $client ) {
    $pid = pcntl_fork();

    if ($pid == -1) {
         die('could not fork');
    } else if ($pid) {
        // parent process
        return;
    }

    $read = '';
    printf( "[%s] Connected at port %d\n", $client->getAddress(), $client->getPort() );

    while( true ) {
        $read = $client->read();
        if( $read != '' ) {
            $client->send( '[' . date( DATE_RFC822 ) . '] ' . $read  );
        }
        else {
            break;
        }

        if( preg_replace( '/[^a-z]/', '', $read ) == 'exit' ) {
            break;
        }
        if( $read === null ) {
            printf( "[%s] Disconnected\n", $client->getAddress() );
            return false;
        }
        else {
            printf( "[%s] recieved: %s", $client->getAddress(), $read );
        }
    }
    $client->close();
    printf( "[%s] Disconnected\n", $client->getAddress() );

}
require "sock/SocketServer.php";
$server = new \Sock\SocketServer();
$server->init();
$server->setConnectionHandler( 'onConnect' );
$server->listen();
你说你还需要一个线程来发送keepalives。我想说,最简单的解决方案是
pnctl\u fork()
在其他进程繁忙时,再使用一个进程发送keepalives


对于keepalive消息,您可以在forked连接处理程序进程中执行此操作。然后,在连接处理程序进程下面的另一个分叉进程中进行实际工作。

请注意,这是一个非常广泛的问题,因此很难给出更具体的答案。好的,我也读过关于pcntl_fork()的文章。但是,如果我的客户机连接到代理,该线程不会持续多久吗?例如,我的客户端连接->启动一个新进程来处理客户端->客户端断开->进程结束。当客户端断开连接时,进程不会自动死亡。如果客户端要在工作完成之前断开连接,那么工作进程池可能应该完全分离,客户端只需与后台工作进程使用的队列进行交互。该进程必须无限期保持打开状态以保持连接打开/发送保持活动的数据包。但是,在队列的情况下,线程如何检查队列以及发送保持活动的数据包?请注意,这是一个非常广泛的问题,因此很难给出更具体的答案。好的,我也读过关于pcntl_fork()的文章。但是,如果我的客户机连接到代理,该线程不会持续多久吗?例如,我的客户端连接->启动一个新进程来处理客户端->客户端断开->进程结束。当客户端断开连接时,进程不会自动死亡。如果客户端要在工作完成之前断开连接,那么工作进程池可能应该完全分离,客户端只需与后台工作进程使用的队列进行交互。该进程必须无限期保持打开状态以保持连接打开/发送保持活动的数据包。但是,对于队列,线程如何检查队列以及发送保持活动的数据包?