Perl Mojolicious - How to make it handle multiple connections at once?
Asked Answered
F

4

5

I setup a quick Mojolicious server like this:

use Mojolicious::Lite;

get '/' => sub {
    my $self = shift;

    sleep 5; #sleep here, I'm testing multiple connections at once

    $self->render_text('Hello World!');
};

app->start;

I then start it with: perl Mojolicious.pl daemon --listen=https://127.0.0.1:3000

Problem is, if I run this command concurrently:

time curl https://127.0.0.1:3000/ -k

It seems to only use 1 thread for requests, because if I make multiple requests at once, they can take much longer than 5 seconds. It's as if they are all queued up.

Am I missing something here? I'm wanting to use Mojolicous, but only if it can handle more than one client at a time.

Funkhouser answered 20/7, 2011 at 21:34 Comment(0)
H
9

mojo daemon is a standalone HTTP server meant for development use, not production, and it only runs a single thread. For production you would want to either use the fastcgi option and a FastCGI-supporting webserver, or install a nice PSGI-compatible server like Starman or Starlet or Plack::Handler::FCGI or Fastpass and then do

plackup -s Starman --port 3000 Mojolicious.pl
Hu answered 20/7, 2011 at 21:55 Comment(2)
So if I set this up to run in Apache, for example. It wouldn't have the issue at all? I just noticed putting a call to fork, makes it work running under daemon, however.Funkhouser
Additional question, if this is setup for FastCGI, will it run a new process for each request?Funkhouser
Z
3

I recommend Reading The Fine Manual of Mojolicious. The Guides are very important. Specifically the sections regarding Hypnotoad - the built-in pre-forking webserver.

Zofiazoha answered 25/7, 2011 at 22:58 Comment(0)
T
2
use AnyEvent;
use Mojolicious::Lite;

my @stack = ();

get '/' => sub {
    my $self = shift;

    $self->render_later;
    push @stack, AnyEvent->timer ( after => 5, cb => sub {
        $self->render_text('Hello World!');
    });
};

app->start;
Thirzia answered 1/2, 2012 at 18:47 Comment(0)
S
0

The painless way to achieve multiple connections at once is to replace "daemon" for "prefork" (it may even works better than hypnotoad):

From:

app->start('daemon', '-l', 'http://*:8000');

To:

app->start('prefork', '-l', 'http://*:8000');

You can test it yourself with:

#!/usr/bin/perl -wl

use Mojolicious::Lite;

get '/' => sub {
    my $self = shift;
    for(my $wait = 10; $wait > 0; $wait--) {
        sleep(1);
    }
    $self->render(text => "OK");
};

# Uncomment to test hypnotoad. execute: hypnotoad ./this_script.pl
#app->config(hypnotoad => {listen => ['http://*:8000']});
#app->start;

# Test Daemon: (Uncomment next line)
#app->start('daemon', '-l', 'http://*:8000');

# Test Prefork: (Uncomment next line)
app->start('prefork', '-l', 'http://*:8000');

This is the benchmark:

$ ab -n 10 -c 10 -s 120 http://localhost:8000/ :

Results:

(totals)         min  mean[+/-sd] median   max       total time
daemon:         11008 92020 28464.5 101021  101022   101.022 seconds
hypnotoad:      10017 31525 18811.0 49030   49033    49.036 seconds
prefork:        20018 24020 5165.0  20020   30022    30.029 seconds

Ideally it would be that the total time would be close to 10 seconds... but I haven't find a way to improve those times (yet).

Stillmann answered 6/6, 2016 at 5:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.