【问题标题】:Can I limit the number of connections for Mojo::IOLoop?我可以限制 Mojo::IOLoop 的连接数吗?
【发布时间】:2018-08-20 19:31:33
【问题描述】:

我正在使用 Mojo::UserAgent 对 Web API 进行递归调用。

有时这会失败 - 我怀疑是因为 API 对来自一个客户端的调用数量有限制。

是否可以限制 Mojo::IOLoop 的并发调用数?

我希望能够限制或计数并等待。

这是进行调用的代码:

my $ua = Mojo::UserAgent->new();

my $loop = Mojo::IOLoop->singleton;
$loop->max_connections(100);
$loop->max_accepts(100);

my $url = Mojo::URL->new('https://outlook.office365.com/EWS/Exchange.asmx');
# authentication omitted

# start navigating the org tree
tree($ua, 'some.person@acme.com');

sub tree {
    my ($ua, $email) = @_;

    my $xml = $mt->vars(1)->render($template, { name =>  $email });

    my $tx = $ua->build_tx(POST => $url =>
           {
            'Content-Type' => 'text/xml', 
            'Accept-Encoding' => 'None' 
            }
            => $xml);
    my $p = $ua->start_p($tx);

    $p->then(sub {
         my $tx = shift;
         my $dom = $tx->res->dom;
         my $reports = $dom->find('DirectReports Mailbox EmailAddress');
         if ($reports->size) {
             my @reports = @{$reports->map(sub { shift->all_text })->to_array};
             for (@reports) {
             print $email, $_;
             tree($ua, $_)
             }
         }
         })
    ->catch(sub {
            my $err = shift;
            warn "Connection error: $err";
            warn join ' ', @_;
    });
}

$loop->start;

这是发布的模板:

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:xsd="http://www.w3.org/2001/XMLSchema"
           xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
  <soap:Header>
    <t:RequestServerVersion Version="Exchange2013_SP1" />
  </soap:Header>
  <soap:Body>
    <ResolveNames xmlns="http://schemas.microsoft.com/exchange/services/2006/messages"
                  xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"
          SearchScope="ActiveDirectory"
          ContactDataShape="AllProperties"
                  ReturnFullContactData="true">
      <UnresolvedEntry><%= $name %></UnresolvedEntry>
    </ResolveNames>
  </soap:Body>
</soap:Envelope>

这将返回一个 XML 文件,其中包含 - 除其他外 - 所有直接下属的电子邮件,然后用于进一步递归。显然不能发布。

【问题讨论】:

  • 也许我不明白。 max_connections 用于限制并发连接。默认为 1,000,您将其设置为 100。metacpan.org/pod/Mojo::IOLoop#max_connections
  • @UncleCarl 它说传入连接,而不是传出。这是一个网络爬虫,而不是网络服务器。
  • 这不是完整的代码。 $loop 怎么知道要运行什么?
  • @simbabque - 这 完整的代码,除了省略 URL 和类似的会泄露太多上下文的代码。我会承认无知和货物崇拜。我的目标是递归地向提供组织树连接的 API 发出请求。然而,API 拒绝同时处理超过一定数量的连接(可能约为 100 个)——这就是我想要限制的。可能以错误的方式 - 道歉。
  • 只需添加一些 example.org 网址。我不明白程序是如何启动的。有了这个,我也许能帮上忙。

标签: perl mojolicious


【解决方案1】:

听起来你想要Mojo::UserAgent::Role::Queued,但这是整个模块:

package Mojo::UserAgent::Role::Queued;
use Mojo::Base '-role';
use Scalar::Util 'weaken';

our $VERSION = "1.10";
use Mojo::UserAgent::Role::Queued::Queue;

has max_active => sub { shift->max_connections };

around start => sub {
  my ($orig, $self, $tx, $cb) = @_;
  state $queue //= Mojo::UserAgent::Role::Queued::Queue->new(
    max_active => $self->max_active,
    callback   => sub { $self->$orig(@_); }
  );
  if ($cb) {
    $tx->on(finish => sub { $queue->tx_finish(); });
    $queue->on( queue_empty => sub { $self->emit('queue_empty') });
    $queue->enqueue([$tx, $cb]);
  }
  else {
    return $orig->($self, $tx);    # Blocking calls skip the queue
  }
};

它创建一个队列,知道它可以同时处理多少个连接。它包装了start,因此在连接数低于您的阈值之前它不会运行。

我已经通过计算上一个时间段的连接数来限制速率。

【讨论】:

  • 耶耶!就在我准备用 Minion 队列实现它的前一秒。谢谢。
  • 我推荐使用实际的模块,因为这不是完整的代码——它使用了一个很小的实用程序类 (:::Queue),这里没有复制。此外,当前版本 (1.15) 删除了使用状态来创建队列,这具有使您的 Mojo::UserAgent 对象成为单例的奇怪副作用。
猜你喜欢
  • 2016-08-08
  • 1970-01-01
  • 2017-10-07
  • 2023-03-14
  • 1970-01-01
  • 2019-02-22
  • 1970-01-01
  • 2012-02-27
  • 1970-01-01
相关资源
最近更新 更多