我正在努力让这个原则起作用:
以下是stompproducer.php
的30行:
<?php
function msg($txt)
{
echo date('H:i:s > ').$txt."\n";
}
$queue = '/aaaa';
$msg = 'bar';
if (count($argv)<3) {
echo $argv[0]." [msg] [nb to send]\n";
exit(1);
}
$msg = (string)$argv[1];
$to_send = intval($argv[2]);
try {
$stomp = new Stomp('tcp://localhost:61613');
while (--$to_send) {
msg("Sending...");
$result = $stomp->send(
$queue,
$msg." ". date("Y-m-d H:i:s"),
array('receipt' => 'message-123')
);
echo 'result='.var_export($result,true)."\n";
msg("Done.");
}
} catch(StompException $e) {
die('Connection failed: ' . $e->getMessage());
}
以下是stompconsumer.php
的30行:
<?php
$queue = '/aaaa';
$_waitTimer=5000000;
$_timeLastAsk = microtime(true);
function msg($txt)
{
echo date('H:i:s > ').$txt."\n";
}
try {
$stomp = new Stomp('tcp://localhost:61613');
$stomp->subscribe($queue, array('activemq.prefetchSize' => 40));
$stomp->setReadTimeout(0, 10000);
while (true) {
$frames_read=array();
while ($stomp->hasFrame()) {
$frame = $stomp->readFrame();
if ($frame != null) {
array_push($frames_read, $frame);
}
if (count($frames_read)==40) {
break;
}
}
msg("Nombre de frames lues : ".count($frames_read));
msg("Pause...");
$e=$_waitTimer-(microtime(true)-$_timeLastAsk);
if ($e>0) {
usleep($e);
}
if (count($frames_read)>0) {
msg("Ack now...");
foreach ($frames_read as $frame) {
$stomp->ack($frame);
}
}
$_timeLastAsk = microtime(true);
}
} catch(StompException $e) {
die('Connection failed: ' . $e->getMessage());
}
我无法设法做同步生产者,即等待消费者确认的生产者。如果您运行我在这里完成的示例,您将看到生产者即时发送所有消息,然后退出,在调用$stomp->send()
时,所有“真实”类似“ok”结果。
我还没有找到好的例子,也没有找到一个简单的阻塞样本的好文档。
在消费者发送其确认消息之前,我该如何让生产者阻止?
答案 0 :(得分:0)
从问题看起来,您正在寻找请求/响应类型的消息传递模式。这是你必须自己实现的东西,因为你引用的STOMP确认只是代表消费者向消息代理发送消息,生产者不知道这一点。请求响应涉及在出站消息上设置回复地址,然后在发送下一条消息之前等待接收对该地址的响应。有很多文章记录了这种事情,例如one。
或者,如果您只需要知道代理是否已收到来自客户端的消息并将其保留,那么您可以使用STOMP内置的receipt机制让经纪人向您发送收据,表明它已处理您发送的邮件。但是,这并不能保证消费者已经处理了消息。
答案 1 :(得分:0)
首先想到的是:看看这个stomp插件:
http://activemq.apache.org/message-redelivery-and-dlq-handling.html
我可以做的另一个解决方法是: 在生产者方面: 1.更改您的生产者以发送持久性消息
在您的消费者方面: 使用计时器。 1.读取消息/帧,直到达到空或最大上限。 2.创建CURL请求和空的打包消息列表 3.将服务器休眠5秒
你肯定需要进一步测试,但应该有效。一旦进程唤醒,您应该能够读取所有排队的消息。
需要考虑的事项: - 持久消息需要到期时间 - 您需要在消费者方面确认,以确保更新已有消息的状态。使用ACK = client,以便确认所有已确认的消息 - 如果您不必等待CURL回复,情况会更容易。 - 开箱即用,不支持从消费者(服务器端)发送ACK。
祝你好运
答案 2 :(得分:0)
我记得,你可以试试reactphp / stomp库。 这是一个可以帮助您的事件驱动库。特别看看ad的核心功能addPeriodicTimer
https://github.com/reactphp/stomp
干杯