簡體   English   中英

如何使用Perl的AnyEvent :: RabbitMQ正確地與RabbitMQ斷開連接?

[英]How to disconnect from RabbitMQ properly using Perl's AnyEvent::RabbitMQ?

我想以正確的方式與RabbitMQ斷開連接。 通過查看 Perl的AnyEvent :: RabbitMQ (我正在使用) 的源代碼 ,我發現close方法似乎關閉了所有打開RabbitMQ的通道。

所以我

  1. 連接到RabbitMQ
  2. 打開了一個頻道
  3. 宣布交換
  4. 綁定到那個交易所
  5. 宣布一個隊列
  6. 綁定到該隊列
  7. AnyEvent::RabbitMQ實例上執行close方法(而不是::Channel實例)

連接似乎已關閉,但RabbitMQ日志顯示“AMQP連接”是“connection_closed_abruptly”。

以下是該連接的完整RabbitMQ日志:

=INFO REPORT==== 14-Jan-2016::10:02:15 ===
accepting AMQP connection <0.10868.0> (127.0.0.1:57764 -> 127.0.0.1:5672)

=WARNING REPORT==== 14-Jan-2016::10:02:16 ===
closing AMQP connection <0.10868.0> (127.0.0.1:57764 -> 127.0.0.1:5672):
connection_closed_abruptly

以下是示例代碼:

#!/usr/bin/perl
use strictures 1;

use AnyEvent::RabbitMQ;
use Data::Printer;

my ( $rabbitmq, $rabbitmq_channel );

my $condvar = AnyEvent->condvar;

$rabbitmq = AnyEvent::RabbitMQ->new->load_xml_spec()->connect(
  host       => '127.0.0.1',
  port       => 5672,
  user       => 'guest',
  pass       => 'guest',
  vhost      => '/',
  timeout    => 1,
  tls        => 0,
  tune       => { heartbeat => 1 },
  on_success => sub {
    ($rabbitmq) = @_;
    $rabbitmq->open_channel(
      on_success => sub {
        ($rabbitmq_channel) = @_;
        $rabbitmq_channel->confirm;
        $rabbitmq_channel->declare_exchange(
          exchange   => 'test_exchange',
          type       => 'fanout',
          on_success => sub {
            $rabbitmq_channel->bind_exchange(
              source      => 'test_exchange',
              destination => 'test_exchange',
              routing_key => '',
              on_success  => sub {
                $rabbitmq_channel->declare_queue(
                  queue      => 'test_queue',
                  on_success => sub {
                    $rabbitmq_channel->bind_queue(
                      queue       => 'test_queue',
                      exchange    => 'test_exchange',
                      routing_key => '',
                      on_success  => sub {
                        $rabbitmq->close;
                        undef $rabbitmq;
                      },
                      on_failure => sub { $condvar->send( __LINE__, @_ ) },
                    );
                  },
                  on_failure => sub { $condvar->send( __LINE__, @_ ) },
                );
              },
              on_failure => sub { $condvar->send( __LINE__, @_ ) },
            );
          },
          on_failure => sub { $condvar->send( __LINE__, @_ ) },
        );
      },
      on_failure => sub { $condvar->send( __LINE__, @_ ) },
      on_return  => sub { $condvar->send( __LINE__, @_ ) },
      on_close   => sub { $condvar->send( __LINE__, @_ ) },
    );
  },
  on_failure      => sub { $condvar->send( __LINE__, @_ ) },
  on_read_failure => sub { $condvar->send( __LINE__, @_ ) },
  on_return       => sub { $condvar->send( __LINE__, @_ ) },
  on_close        => sub { $condvar->send( __LINE__, @_ ) },
);

my $reason = [ $condvar->recv ];
p $reason;

如何使用Perl的AnyEvent::RabbitMQ正確地與RabbitMQ斷開連接?

有參考周期的指標。 這些可以防止結構被正確破壞。

  1. my $rabbitmq; $rabbitmq = ...my $rabbitmq; $rabbitmq = ...參考周期的可能性。

  2. my $rabbitmq_channel; $rabbitmq_channel = ... ”大my $rabbitmq_channel; $rabbitmq_channel = ...參考周期的可能性。

  3. $rabbitmq_channel由(存儲在)旗下$rabbitmq ,但它也被抓獲$rabbitmq_channel的事件處理程序。

標記為<===的更改將替換不可接受的代碼。

標有<---的更改可能是必要的。 如果回調中未定義$rabbitmq_channel ,請刪除此更改。

use Scalar::Util qw( weaken );

my $done_cv = AnyEvent->condvar;

my $rabbitmq = AnyEvent::RabbitMQ->new->load_xml_spec()->connect(  # <===
  host       => '127.0.0.1',
  port       => 5672,
  user       => 'guest',
  pass       => 'guest',
  vhost      => '/',
  timeout    => 1,
  tls        => 0,
  tune       => { heartbeat => 1 },
  on_success => sub {
    my ($rabbitmq) = @_;  # <===
    $rabbitmq->open_channel(
      on_success => sub {
        my ($rabbitmq_channel) = @_;  # <===
        {  # <---
          my $rabbitmq_channel = weaken($rabbitmq_channel);  # <---
          $rabbitmq_channel->confirm;
          $rabbitmq_channel->declare_exchange(
            exchange   => 'test_exchange',
            type       => 'fanout',
            on_success => sub {
              $rabbitmq_channel->bind_exchange(
                source      => 'test_exchange',
                destination => 'test_exchange',
                routing_key => '',
                on_success  => sub {
                  $rabbitmq_channel->declare_queue(
                    queue      => 'test_queue',
                    on_success => sub {
                      $rabbitmq_channel->bind_queue(
                        queue       => 'test_queue',
                        exchange    => 'test_exchange',
                        routing_key => '',
                        on_success  => sub { $done_cv->send( __LINE__, @_ ) },  # <===
                        on_failure => sub { $done_cv->send( __LINE__, @_ ) },
                      );
                    },
                    on_failure => sub { $done_cv->send( __LINE__, @_ ) },
                  );
                },
                on_failure => sub { $done_cv->send( __LINE__, @_ ) },
              );
            },
            on_failure => sub { $done_cv->send( __LINE__, @_ ) },
          );
        }  # <---
      },
      on_failure => sub { $done_cv->send( __LINE__, @_ ) },
      on_return  => sub { $done_cv->send( __LINE__, @_ ) },
      on_close   => sub { $done_cv->send( __LINE__, @_ ) },
    );
  },
  on_failure      => sub { $done_cv->send( __LINE__, @_ ) },
  on_read_failure => sub { $done_cv->send( __LINE__, @_ ) },
  on_return       => sub { $done_cv->send( __LINE__, @_ ) },
  on_close        => sub { $done_cv->send( __LINE__, @_ ) },
);

my $reason = [ $done_cv->recv ];
p $reason;

我希望這有幫助。

問題是AnyEvent :: RabbitMQ.pm庫本身的一個錯誤。 我不確定如何修復sub close本身,但關鍵部分是它永遠不會執行在全局解構期間將Connection::CloseConnection::CloseOk方法發送到RabbitMQ服務器的代碼。 設置AMQP連接后,可以通過執行以下操作進行確認。

$rabbitmq->_push_write(Net::AMQP::Protocol::Connection::Close->new());
$rabbitmq->_push_write(Net::AMQP::Protocol::Connection::CloseOk->new());

這是一個黑客攻擊,所以我正在努力正確的方式,並希望維護者將接受拉取請求。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM