我一直在对ReactPHP进行一些测试,因为它看起来非常棒.对于简单的套接字服务器,我使用以下react/socket代码对其进行了测试.
$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server($loop);
$socket->on('connection', function ($conn) {
echo 'New client !';
$conn->on('data', function ($data) use ($conn) {
$conn->write("Wow, some data, such cool\n");
$conn->close();
});
});
$socket->listen(1337);
$loop->run();
Run Code Online (Sandbox Code Playgroud)
直到这一点,没有问题.服务器显示New client !
何时连接客户端并且客户端收到响应.
但我做了一个新的测试,对data
事件进行了更多的处理.为了说明我的话,我将添加一个for
需要几毫秒才能完成的循环:
$conn->on('data', function ($data) use ($conn) {
$conn->write("Wow, some data, such cool\n");
for ($i=0; $i<10000000; $i++); // here
$conn->close();
});
Run Code Online (Sandbox Code Playgroud)
在这种情况下,有10个客户端,客户端将Wow, some data, such cool
在所有客户端处理后显示文本(所以~2秒),但服务器将显示New client !
而不等待.
所以在这里我缺乏理解,ReactPHP是一个异步I/O,但PHP是单线程的,如果输入和输出之间有很多处理,那将阻止所有客户端.
注意:这是不一样的这个问题,它利用
MessageComponentInterface
.我正在使用WampServerInterface
,所以这个问题具体涉及那个部分.我需要一个代码示例和解释的答案,因为我可以看到这对将来的其他人有帮助.
我正在使用Ratchet和ZeroMQ的WAMP部分,我目前有推送集成教程的工作版本.
我正在尝试执行以下操作:
我有点(1)和(2)工作,但我遇到的问题是第三个:
首先:如何仅向每个特定用户发送数据?广播将它发送给每个人,除非"主题"最终可能是个人用户ID?
其次:我有一个很大的安全问题.如果我发送哪个用户ID想要从客户端订阅,这似乎是我需要的,那么用户可以将变量更改为另一个用户的ID,而是返回他们的数据.
第三:我必须运行一个单独的php脚本,其中包含zeromq的代码以启动实际的循环.我不确定这是最好的方法,我宁愿让它完全在代码库中工作,而不是单独的php文件.这是我需要排序的主要领域.
以下代码显示了我目前拥有的内容.
我按字面输入php bin/push-server.php
来运行它.订阅和取消订阅将输出到此终端以进行调试.
$loop = React\EventLoop\Factory::create();
$pusher = Pusher;
$context = new React\ZMQ\Context($loop);
$pull = $context->getSocket(ZMQ::SOCKET_PULL);
$pull->bind('tcp://127.0.0.1:5555');
$pull->on('message', array($pusher, 'onMessage'));
$webSock = new React\Socket\Server($loop);
$webSock->listen(8080, '0.0.0.0'); // Binding to 0.0.0.0 means remotes can connect
$webServer = new Ratchet\Server\IoServer(
new Ratchet\WebSocket\WsServer(
new Ratchet\Wamp\WampServer(
$pusher
) …
Run Code Online (Sandbox Code Playgroud) 我开始使用http://reactphp.org/来处理HTTP请求.
我运行多个在不同端口上运行的反应工作者,然后使用Nginx作为负载平衡来处理请求.像这样
upstream backend {
server 127.0.0.1:13300;
server 127.0.0.1:13301;
.....
}
Run Code Online (Sandbox Code Playgroud)
一切运作良好的预期.
问题是如何获得reactphp过程状态的统计数据.当前有多少进程处于空闲状态(等待新请求),有多少进程在请求下工作,等等.
是否有现成的解决方法?
或者想一想如何手动处理流程统计.
示例 - 将写入锁定到某个缓存进程状态.何时是启动请求进程 - 增加处理进程数,完成请求时 - 增加空闲进程数.
我有一个小的websocket服务器,运行在一组库之上:
和
php-zmq
包装器.代码与教程中的代码基本相同.
eventloop正确启动,用户可以连接到服务器,他们正在获取正确的消息,当另一方推送东西时,但过了一段时间,通常是几天(取决于使用情况)消息停止到达.
根本没有压倒性的使用 - 目前只有一两个前端开发人员连接,因为这是一个开发阶段.
循环正在运行,它在连接时正确返回HTTP 101切换协议,但不会广播之前正确广播的消息.没有任何错误.重新启动事件循环会有所帮助.
1)是什么导致这种情况?有人遇到过类似的行为吗?
2)你能推荐一种方法,我可以在长时间运行的事件循环过程中调试它吗?
目前,我必须停止循环,更改代码(添加日志记录调用),再次重新启动循环并等待它再次出错,这至少是乏味的.
任何帮助非常感谢.
React PHP如何处理异步非阻塞I/O?
Nodejs使用其事件队列来处理不同线程上的I/O. 它使用libuv.就像在PHP中一样,React如何处理单个线程上的非阻塞I/O进程?
我必须连接具有异步套接字连接的远程服务器并检索数据.我可以连接,但有一个问题.
包裹是按件发送的.我有两个选择; 我可以设置缓冲区并将整个包装整合在一起,或者在完成所有传输后组合碎片.我认为第一个选项(缓冲物)是正确的方法.
我正在定义缓冲区大小,但它在第一部分不起作用.在其他部分,它的工作原理,但使用这种方法,我不能将整个包装整体,因为第一部分限制为5,24 Kb.
你可以在下面找到我的代码:
$loop = React\EventLoop\Factory::create();
$dnsResolverFactory = new React\Dns\Resolver\Factory();
$dns = $dnsResolverFactory->createCached('8.8.8.8', $loop);
$connector = new React\SocketClient\Connector($loop, $dns);
$connector->create( ENDPOINT_IP , ENDPOINT_PORT )->then(function (React\Stream\Stream $stream) use ($loop) {
$command = '{C:"EL",bmId:43,inst:"my_instance",tok:"my_token"}';
$command_length = strlen($command);
$command_length = pack("N", $command_length);
$stream->write($command_length);
$stream->write($command);
$stream->bufferSize = 999999;
$stream->on('data', function ($data) {
$package = substr($data, 0, 4);
$unpack = unpack('N', $package); // I'm getting whole package size
echo $data;
});
});
$loop->run();
Run Code Online (Sandbox Code Playgroud)
我试图$stream->on('data', function ($data) {
在行下定义一个缓冲区大小,但你猜它失败了.我不知道如何正确处理它.
提前致谢.
我正在使用Laravel 4,因为我正在浏览React PHP,如果有任何方法可以使用React PHP和Laravel一起游荡.
有没有任何示例从使用Laravel的React PHP开始?或任何与Laravel一起使用的建议?
问题与仅使用react\stomp从RabbitMQ消耗N个消息非常相关,单独确认它们然后退出,但更一般.
例如,我的I/O操作很慢:
$port = 4000;
$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server($loop);
$socket->on('connection', function ($conn) use ($loop){
$conn->on('data', function ($data) use ($conn, $loop) {
if ($data == 42) {
// this instantly stop the loop
$loop->stop();
}
$process = new React\ChildProcess\Process('sleep 5; echo ' . $data);
$loop->addTimer(0.001, function($timer) use ($process, $conn) {
$process->start($timer->getLoop());
$process->stdout->on('data', function($output) use ($conn) {
if ($output) {
$conn->write("> $output");
}
});
});
});
});
echo "Socket server listening on port $port.\n";
echo …
Run Code Online (Sandbox Code Playgroud) 我有一个websocket应用程序,我正在构建一个游戏,基于Ratchet,它使用React事件循环.在这个脚本的开头,我已经想出了如何实现一个periodictimer,每秒向游戏发送一个脉冲,然后执行ticks和combat rounds.这非常有效.
但是,我最近意识到我还需要添加"滞后"客户端的功能,或者暂停在函数中执行.例如,如果玩家被击晕,或者我希望NPC在回复触发器之前等待1.5秒,以获得更"逼真"的会话感觉.
这个功能是内置在反应库中的,还是我必须通过其他方式实现的?经过一些研究,看起来我可能正在寻找pthreads,看看这个问题/答案:如何在PHP应用程序中使用多线程
为了更清楚我想要实现的目标,请以此代码为例:
function onSay($string)
{
global $world;
$trigger_words = array(
'hi',
'hello',
'greetings'
);
$triggered = false;
foreach($trigger_words as $trigger_word)
{
if(stristr($string, $trigger_word))
{
$triggered = true;
}
}
if($triggered)
{
foreach($world->players as $player)
{
if($player->pData->in_room === $this->mobile->in_room)
{
sleep(1);
$this->toChar($player, $this->mobile->short . " says '`kOh, hello!``'");
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
显然,这不起作用,因为sleep(1)函数将暂停整个服务器进程.
任何见解将不胜感激.谢谢!
更新:我的服务器脚本:
require 'vendor/autoload.php';
require 'src/autoload.php';
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use React\Socket\Server as Reactor;
use React\EventLoop\Factory as LoopFactory;; …
Run Code Online (Sandbox Code Playgroud) 我正在使用棘轮php.我是这样开始的:
$loop = \React\EventLoop\Factory::create();
$webSock = new \React\Socket\Server($loop);
$webSock->listen($this->port, $this->host);
$webServer = new \Ratchet\Server\IoServer(
new \Ratchet\Http\HttpServer(
new \Ratchet\WebSocket\WsServer(
new PusherServer()
)
),
$webSock
);
return $loop;
Run Code Online (Sandbox Code Playgroud)
现在,在我onMessage()
的Pusherserver
班级(实现MessageComponentInterface
)中,我想执行一个长期的阻塞任务.这将是一个HTTP请求,可能需要十秒钟才能完成.
如何在onMessage()
执行上一个HTTP请求时自由处理其他请求?我不能使用pthreads,因为我无权更改我已经给出的php版本(这是线程安全的).
php ×10
reactphp ×10
asynchronous ×3
ratchet ×3
sockets ×2
websocket ×2
zeromq ×2
asyncsocket ×1
event-loop ×1
laravel ×1
laravel-4 ×1
nginx ×1