Activemq和Php Stomp:同步生产者样本

时间:2015-01-03 18:28:17

标签: php activemq stomp

我正在努力让这个原则起作用:

  • 发送一个消息(1)的生产者并等待包含某些结果的ack(实际上是操作的json结果)
  • 消费者每5秒检查所有待处理消息 ,并在一行中处理所有消息,并在一行中确认所有消息,然后再等待5秒(无限循环)。< / LI>

以下是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”结果。 我还没有找到好的例子,也没有找到一个简单的阻塞样本的好文档。

在消费者发送其确认消息之前,我该如何让生产者阻止?

注意:我已经在stackoverflow herehere上阅读了所有文档here和stomp php问题。

3 个答案:

答案 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

干杯