1

我正在使用 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 帧。

我的问题是,有没有什么办法可以做到,既可以订阅多个主题,又可以接收交易收据?还是有更好/更标准的方法来处理它?

任何提示或建议都将受到欢迎,谢谢!我也在 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。

所以要么我做错了什么,要么它不能以这种方式工作。

4

1 回答 1

1

好的,我试过了,效果很好。但你是接收框架的人。那么为什么服务器要给你发送一个收据帧呢?

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

更新

啊,好的,你想ack通过使用交易来保护。因此,让我们看一下源代码:有一种方法send_transactional可能可以完成您想做的事情(但它使用的是SEND框架而不是ACK)。

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

于 2011-09-27T06:53:36.227 回答