Tuesday, December 21, 2010

Day 21: parallel HTTP requests with Mojo::Client

Two years ago I followed the development of Mojo very closely. Plack/PSGI did not exist and I was appealed by Mojos very few dependencies. I even wrote an mod_perl2 handler for it. My interest for Mojo is gone (Plack filled that need much better), but Sebastian has some very nice modules in his distribution. One of them is Mojo::Client - an asynchronous HTTP 1.1 client:
#!/usr/bin/perl
# filename: mojo-client.pl
use strict;
use warnings;
use Mojo::Client;
my $mojo = Mojo::Client->new;
my $url  = 'http://localhost:5000/?sleep=';
my @tx   = ();
foreach (2 .. 4) {
    push @tx, scalar $mojo->build_tx(GET => $url.$_);
}
$mojo->queue(@tx);
$mojo->start;
my $slept = 0;
foreach my $tx (@tx) {
    $slept += $tx->res->json->{slept};
}
print "Slept $slept seconds.\n";

To test this, I wrote a small app.psgi:
#!/usr/bin/perl
# filename: app.psgi
use strict;
use warnings;
use Plack::Request;
my $app = sub {
    my $req = Plack::Request->new(shift);
    my $sleep = sleep($req->parameters->{sleep} || 5);
    return [
        200,
        ['Content-Type', 'application/json'],
        ['{"slept":'.$sleep.'}'],
    ];
};

Fire up starman (or any other PSGI web server capable of parallel requests) and try it:
$ time perl mojo-client.pl
Slept 9 seconds.
real 0m4.170s
user 0m0.130s
sys 0m0.030s

The numbers are the same as with the Gearman example. We "wait" 9 seconds, but it only takes a little bit over 4 seconds.

As a counter example the results with plackup (single-request server):
$ plackup &
HTTP::Server::PSGI: Accepting connections at http://0:5000/
$ time perl mojo-client.pl
Slept 9 seconds.
real 0m9.178s
user 0m0.180s
sys 0m0.000s

Mojo::Client has much more to offer than parallel processing. It also supports websocket requests.

Did you notice the $tx->res->json call? Mojo::Client has built-in JSON support. Truly Web 2.0 :)

Links:

1 comment:

  1. Meh. I prefer AnyEvent::HTTP for making parallel requests.

    ReplyDelete