如何使用Net :: Stomp和带有receive_frame的事务

时间:2011-09-26 17:32:01

标签: perl activemq stomp

我正在使用Net :: Stomp调整一些现有代码,以便能够处理单个主题,以便能够处理多个主题。任何人都可以告诉我这种方法是否可行?它现在不能正常工作,因为它预计收到交易,它会在另一个主题上获得第一条消息。在我尝试修复它之前,我想知道我是不是正在吠叫错误的树。

以下是工作流程的内容:

# first subscribe to three different queues
for $job (qw/ JOB1 JOB2 JOB3 /){
$stomp->subscribe({
   "ack" => "client",
   "destination" => "/queue/$job"
});

# listen on those three channels...
while($stomp->can_read){

   $frame = $stomp->receive_frame();

   # ... receives a message for JOB1
   # and to start a transaction send a BEGIN frame that looks like this:

    bless({
    command => "BEGIN",
    headers => {
             receipt => "0002",
            transaction => "0001",
       },
    }, "Net::Stomp::Frame")

   # Then looks for a receipt on that frame by calling
   $receipt = $stomp->receive_frame()

不幸的是,它期待一个RECEIPT帧,它实际上获得了在JOB2队列中等待的下一个MESSAGE帧。

我的问题是,有没有办法让它工作,既可以订阅多个主题,又可以收到交易收据?或者是否有更好/更标准的方法来处理它?<​​/ p>

非常欢迎任何提示或建议,谢谢!我也在ActiveMQ列表上交叉发布这个问题,希望没问题: - /

*更新*

这是一个完整的复制案例:

use Net::Stomp;

use strict;

my $stomp = Net::Stomp->new( { hostname => 'bpdeb', port => '61612' } );
$stomp->connect( { login => 'hello', passcode => 'there' } );

# pre-populate the two queues
$stomp->send( { destination => '/queue/FOO.BAR', body => 'test message' } );
$stomp->send( { destination => '/queue/FOO.BAR2', body => 'test message' } );


# now subscribe to them
$stomp->subscribe({ destination => '/queue/FOO.BAR',
                   'ack'        => 'client',
                   'activemq.prefetchSize' => 1
});
$stomp->subscribe({ destination => '/queue/FOO.BAR2',
                   'ack'        => 'client',
                   'activemq.prefetchSize' => 1
});

# read one frame, then start a transaction asking for a receipt of the 
# BEGIN message
while ($stomp->can_read()){

    my $frame = $stomp->receive_frame; 
    print STDERR "got frame ".$frame->as_string()."\n";


    print STDERR "sending a BEGIN\n";
    my($frame) = Net::Stomp::Frame->new({
        command => 'BEGIN',
            headers => {
            transaction => 123,
            receipt     => 456,
        },
    });

    $stomp->send_frame($frame);

    my $expected_receipt = $stomp->receive_frame;
    print STDERR "expected RECEIPT but got ".$expected_receipt->as_string()."\n";

    exit;
}

此输出(详细信息已删除)

got frame MESSAGE
destination:/queue/FOO.BAR
....

sending a BEGIN

expected RECEIPT but got MESSAGE
destination:/queue/FOO.BAR2
....

查看网络流量,一旦发送SUBSCRIBE请求,队列中的第一条消息就会通过网络传输到客户端。因此,当我发送BEGIN消息时,来自FOO.BAR2的第一条消息已经在客户端的网络缓冲区中等待,并且客户端直接从其缓冲区中读取FOO.BAR2。

所以要么我做错了,要么就是这样。

1 个答案:

答案 0 :(得分:1)

好的,我试过了,它运行正常。但你是接收框架的人。那么为什么服务器会向您发送收据框?

您正在设置"ack" => "client",这意味着,除非您另有说明,否则服务器会将该帧视为“未送达”。只需将第$receipt = $stomp->receive_frame()行更改为$stomp->ack( { frame => $frame } );

更新

啊,你想通过使用交易来保护ack。我们来看看source:有一个方法send_transactional可能会执行您想要做的事情(但它使用SEND框架代替ACK)。

也许您还应该看一下submitted patch from cloudmark,它为模块添加了几个“安全功能”(不幸的是,当我问他时,模块作者没有说任何关于合并该补丁的内容)。 / p>

相关问题