Php ZMQ订阅服务器在长时间间隔后未收到来自远程服务器的消息
当两个php都在同一台服务器上运行时,以下pubsub php正常工作。但是,当它们在不同的服务器上运行时,它不起作用Php ZMQ订阅服务器在长时间间隔后未收到来自远程服务器的消息,php,sockets,zeromq,publish-subscribe,pyzmq,Php,Sockets,Zeromq,Publish Subscribe,Pyzmq,当两个php都在同一台服务器上运行时,以下pubsub php正常工作。但是,当它们在不同的服务器上运行时,它不起作用 (local)client.php <--> (local)server.php (with sleeptime 300) <= OK (local)client.php <--> (remote)server.php (with sleeptime 300) <= NG (local)client.php(local)server.php
(local)client.php <--> (local)server.php (with sleeptime 300) <= OK
(local)client.php <--> (remote)server.php (with sleeptime 300) <= NG
(local)client.php(local)server.php(带sleeptime 300)我在php中使用ZeroMQ来发送对时间敏感的实时信号。首先,一些理论:互联网工程任务组(IETF)和指定TCP。在这种情况下,感兴趣的属性是用户超时。用户超时在中得到了最好的解释,这是一项建议,旨在实现应用程序之间通信用户超时设置的标准:
传输控制协议(TCP)规范[RFC0793]定义了一个本地、每连接“用户超时”参数,该参数
指定传输数据可能保留的最大时间量
在TCP之前未确认将强制关闭相应的
连接。应用程序可以使用OPEN设置和更改此参数
并发送电话。如果端到端连接中断持续时间更长
超过用户超时时,发送方将不会收到对的确认
任何传输尝试,包括保持生命,它将关闭
发生用户超时时的TCP连接
在没有应用程序指定的用户超时的情况下,TCP
规范[RFC0793]定义了5分钟的默认用户超时。
主机需求RFC[RFC1122]通过
引入两个阈值R1和R2(R2>R1),用于控制
单个段的重新传输尝试次数。它表明
当到达R1时,TCP应通知应用程序
段,并在到达R2时关闭连接。[RFC1122]也
定义R1(3次重传)和R2(100)的建议值
秒),注意SYN段的R2应至少为3
分钟。”
服务器和客户端之间可能有很多设备;你不太可能控制全部(当然,除非是局域网)。由于目前没有跨应用程序和网关商定超时设置的标准;对于防火墙,最好定期发送“保持活动”数据。此外,许多其他问题可能会中断连接,同样,应用程序也可能失败。因此,keep-alive heartbeat实现有助于创建一个健壮的应用程序,使连接保持打开状态并及时发现问题
心碎
根据应用程序的不同,我通常使用1到5秒之间的心跳间隔。客户端统计丢失的心跳,并在信号关闭时做出相应响应(例如,退回到AJAX轮询、提醒用户、重新启动脚本等)。请记住,发布服务器-订阅服务器消息不会排队。如果订阅者错过了它,它就错过了它。如果您希望服务器能够确认接收和客户端连接状态,则需要额外的通信过程。如果客户端宕机一段时间,则无法确定是否已收到所有消息。该系统具有良好的性能和健壮的应用程序设计
“心跳解决了知道同伴是否活着的问题
死。这不是ZeroMQ特有的问题。TCP超时时间较长
(30分钟左右),这意味着不可能知道
是否有同龄人死亡、断开连接或在周末前往
布拉格有一箱伏特加,一个红头发,还有一大笔开支。”
好的,下面是一个使用您的代码的代码示例:
Server.php
<?php
$context = new ZMQContext();
$publisher = new ZMQSocket($context, ZMQ::SOCKET_PUB);
$publisher->bind("tcp://*:5563");
while (true) {
sleep (300);
$publisher->send("A", ZMQ::MODE_SNDMORE);
$publisher->send("We don't want to see this");
$publisher->send("B", ZMQ::MODE_SNDMORE);
$publisher->send("We would like to see this");
}
<?php
$context = new ZMQContext();
$subscriber = new ZMQSocket($context, ZMQ::SOCKET_SUB);
$subscriber->connect("tcp://localhost:5563"); // This is the setting for local server.php. I changed it for server.php at remote.php
$subscriber->setSockOpt(ZMQ::SOCKOPT_SUBSCRIBE, "B");
while (true) {
$address = $subscriber->recv();
$contents = $subscriber->recv();
printf ("[%s] %s%s", $address, $contents, PHP_EOL);
<?php
$context = new ZMQContext();
$publisher = new ZMQSocket($context, ZMQ::SOCKET_PUB);
$publisher->bind("tcp://*:5563");
$i = 0; // Iteration counter to trigger message
while (true) {
$publisher->send('HB'); // Distribute the heartbeat (all clients will subscribe)
sleep (5); // Heartbeat interval
$i++ // Clock that ticks up ~5 seconds at a time (alternatively,
// you could set a variable to store the timestamp of the last time the
// messages (A & B) were sent and then check to see if 5 minutes has elapsed).
if ($i >= 60) {
// 300 seconds--or perhaps a hair more--have elapsed, send the messages
$i = 0; // Rest the clock.
$publisher->send("A", ZMQ::MODE_SNDMORE);
$publisher->send("We don't want to see this");
$publisher->send("B", ZMQ::MODE_SNDMORE);
$publisher->send("We would like to see this");
} // Don't forget to close if statement.
}
<?php
$context = new ZMQContext();
$subscriber = new ZMQSocket($context, ZMQ::SOCKET_SUB);
$SERVERIP = 'Where is the server?'; // Make sure this is correct and no firewall!
$subscriber->connect("tcp://$SERVERIP:5563");
$subscriber->setSockOpt(ZMQ::SOCKOPT_SUBSCRIBE, "B");
$subscriber->setSockOpt(ZMQ::SOCKOPT_SUBSCRIBE, 'HB'); // Subscribe to the heartbeat
$heartMonitor = time(); // Time we started listening.
while (true) {
$address = $subscriber->recv();
$more = $subscriber->getSockOpt(ZMQ::SOCKOPT_RCVMORE); // See if this is a multipart message
if ($more) {
// Message has second part--normally there would be a loop for variable length messages.
$contents = $subscriber->recv();
}
if ($address == 'HB') {
// Message is the heartbeat, would send this to additional
// application components and have them listen for heartbeat as well.
$heartMonitor = time(); // Time last heartbeat received in seconds
}else{
// Message is your content message; Do stuff.
printf ("[%s] %s%s", $address, $contents, PHP_EOL);
$heartMonitor = time(); // It doesn't matter which message was just received, both confirm connection.
}
$timeout = 20; // At least 3 heartbeat signals were missed.
if ($heartMonitor < (time() - $timeout)) {
// Connection lost. Alert user, fallback, or attempt reconnect, etc. here.
break;
}
} // Don't forget to close while loop.
<?php
$context = new ZMQContext();
$subscriber = new ZMQSocket($context, ZMQ::SOCKET_SUB);
$SERVERIP = 'Where is the server?'; // Make sure this is correct and no firewall!
$subscriber->connect("tcp://$SERVERIP:5563");
$subscriber->setSockOpt(ZMQ::SOCKOPT_SUBSCRIBE, "B");
$subscriber->setSockOpt(ZMQ::SOCKOPT_SUBSCRIBE, 'HB'); // Subscribe to the heartbeat
$heartMonitor = time(); // Time we started listening.
while (true) {
$address = $subscriber->recv();
$more = $subscriber->getSockOpt(ZMQ::SOCKOPT_RCVMORE); // See if this is a multipart message
if ($more) {
// Message has second part--normally there would be a loop for variable length messages.
$contents = $subscriber->recv();
}
if ($address == 'HB') {
// Message is the heartbeat, would send this to additional
// application components and have them listen for heartbeat as well.
$heartMonitor = time(); // Time last heartbeat received in seconds
}else{
// Message is your content message; Do stuff.
printf ("[%s] %s%s", $address, $contents, PHP_EOL);
$heartMonitor = time(); // It doesn't matter which message was just received, both confirm connection.
}
$timeout = 20; // At least 3 heartbeat signals were missed.
if ($heartMonitor < (time() - $timeout)) {
// Connection lost. Alert user, fallback, or attempt reconnect, etc. here.
break;
}
} // Don't forget to close while loop.