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 に答える