执行多项操作时的PHP线程

时间:2016-07-07 09:38:28

标签: php

我正在用PHP编写一种代理。

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

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

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

如果这是一个坏主意,这将如何正确完成?

1 个答案:

答案 0 :(得分:0)

在架构上,线程是解决这个问题的好方法,所以你肯定是以正确的方式思考这个问题。不幸的是,PHP不支持Threads!因此,您必须通过pcntl_fork()使用进程Here's an example(不是我的代码),创建一个新进程来处理每个连接而不是一个线程。

/**
 * 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();

你说你还需要一个Thread来发送keepalive。我想说最简单的解决方案是pnctl_fork()一个额外的进程并用它来发送keepalive,而其他进程都很忙。

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