我正在用PHP编写一种代理。
此代理将与服务器建立一些连接,并且如果不需要发送其他命令,则通常每隔一段时间发送一个“ping”数据包来保持连接处于打开状态。
客户端应该能够连接到代理并将其转发到服务器上。在这种情况下,代理将选择当前不忙的连接之一(如果连接了多个客户端,其中一个请求需要一段时间)并使用该非忙连接。
我对它是如何工作的想法:使用RabbitMQ作为队列。客户端向RabbitMQ提交消息并等待响应。在服务器端,每个连接都是它自己的线程,每个线程都会不断地等待RabbitMQ的工作,第一个从RabbitMQ获取消息的连接将满足请求。但是在这种情况下,由于连接线程一直忙着等待工作,如果没有工作,我该如何发送keepalive数据包呢?
如果这是一个坏主意,这将如何正确完成?
答案 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消息,您可以在分叉连接处理程序进程中执行此操作。然后,在连接处理程序进程下的另一个分叉进程中进行实际工作。