Skip to content

Commit

Permalink
added request limit support to the daemons
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Mar 11, 2010
1 parent b6fe77f commit 83853f3
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 74 deletions.
1 change: 1 addition & 0 deletions Changes
@@ -1,6 +1,7 @@
This file documents the revision history for Perl extension Mojolicious.

0.999924 2010-03-08 00:00:00
- Added request limit support to the daemons.
- Added more routes tests. (doubi)
- Cleaned up documentation.
- Cleaned up tests.
Expand Down
53 changes: 30 additions & 23 deletions lib/Mojo/Command/Daemon.pm
Expand Up @@ -18,22 +18,27 @@ __PACKAGE__->attr(usage => <<"EOF");
usage: $0 daemon [OPTIONS]
These options are available:
--clients <number> Set maximum number of concurrent clients, defaults
to 1000.
--group <name> Set group name for process.
--keepalive <seconds> Set keep-alive timeout, defaults to 15.
--listen <locations> Set a comma separated list of locations you want to
listen on, defaults to http://*:3000.
--lock <path> Set path to lock file, defaults to a random
temporary file.
--pid <path> Set path to pid file, defaults to a random
temporary file.
--queue <size> Set listen queue size, defaults to SOMAXCONN.
--reload Automatically reload application when the source
code changes.
--requests <number> Set the maximum number of requests per keep-alive
connection, defaults to 100.
--user <name> Set user name for process.
--clients <number> Set maximum number of concurrent clients,
defaults to 1000.
--group <name> Set group name for process.
--keepalive <seconds> Set keep-alive timeout, defaults to 15.
--keepaliverequests <number> Set maximum number of requests per
keep-alive connection, defaults to 100.
--listen <locations> Set a comma separated list of locations you
want to listen on, defaults to
http://*:3000.
--lock <path> Set path to lock file, defaults to a random
temporary file.
--pid <path> Set path to pid file, defaults to a random
temporary file.
--queue <size> Set listen queue size, defaults to
SOMAXCONN.
--reload Automatically reload application when the
source code changes.
--requests <number> Set the maximum number of requests the
daemon is allowed to handle, defaults to
100.
--user <name> Set user name for process.
EOF


Expand All @@ -49,13 +54,15 @@ sub run {
'clients=i' => sub { $daemon->max_clients($_[1]) },
'group=s' => sub { $daemon->group($_[1]) },
'keepalive=i' => sub { $daemon->keep_alive_timeout($_[1]) },
'listen=s' => sub { $daemon->listen($_[1]) },
'lock=s' => sub { $daemon->lock_file($_[1]) },
'pid=s' => sub { $daemon->pid_file($_[1]) },
'queue=i' => sub { $daemon->listen_queue_size($_[1]) },
reload => sub { $daemon->reload(1) },
'requests=i' => sub { $daemon->max_keep_alive_requests($_[1]) },
'user=s' => sub { $daemon->user($_[1]) }
'keepaliverequests=i' =>
sub { $daemon->max_keep_alive_requests($_[1]) },
'listen=s' => sub { $daemon->listen($_[1]) },
'lock=s' => sub { $daemon->lock_file($_[1]) },
'pid=s' => sub { $daemon->pid_file($_[1]) },
'queue=i' => sub { $daemon->listen_queue_size($_[1]) },
reload => sub { $daemon->reload(1) },
'requests=i' => sub { $daemon->max_requests($_[1]) },
'user=s' => sub { $daemon->user($_[1]) }
);

# Run
Expand Down
84 changes: 46 additions & 38 deletions lib/Mojo/Command/DaemonPrefork.pm
Expand Up @@ -18,33 +18,39 @@ __PACKAGE__->attr(usage => <<"EOF");
usage: $0 daemon_prefork [OPTIONS]
These options are available:
--clients <number> Set maximum number of concurrent clients per child,
defaults to 1.
--daemonize Daemonize parent.
--group <name> Set group name for children.
--idle <seconds> Set time children can be idle without getting
killed, defaults to 30.
--interval <seconds> Set interval for process maintainance, defaults to
15.
--keepalive <seconds> Set keep-alive timeout, defaults to 15.
--listen <locations> Set a comma separated list of locations you want to
listen on, defaults to http://*:3000.
--lock <path> Set path to lock file, defaults to a random
temporary file.
--maxspare <number> Set maximum amount of idle children, defaults to
10.
--minspare <number> Set minimum amount of idle children, defaults to 5.
--pid <path> Set path to pid file, defaults to a random
temporary file.
--queue <size> Set listen queue size, defaults to SOMAXCONN.
--reload Automatically reload application when the source
code changes.
--requests <number> Set maximum number of requests per keep-alive
connection, defaults to 100.
--servers <number> Set maximum number of children, defaults to 100.
--start <number> Set number of children to spawn at startup,
defaults to 5.
--user <name> Set user name for children.
--clients <number> Set maximum number of concurrent clients per
child, defaults to 1.
--daemonize Daemonize parent.
--group <name> Set group name for children.
--idle <seconds> Set time children can be idle without
getting killed, defaults to 30.
--interval <seconds> Set interval for process maintainance,
defaults to 15.
--keepalive <seconds> Set keep-alive timeout, defaults to 15.
--keepaliverequests <number> Set maximum number of requests per
keep-alive connection, defaults to 100.
--listen <locations> Set a comma separated list of locations you
want to listen on, defaults to http://*:3000.
--lock <path> Set path to lock file, defaults to a random
temporary file.
--maxspare <number> Set maximum amount of idle children,
defaults to 10.
--minspare <number> Set minimum amount of idle children,
defaults to 5.
--pid <path> Set path to pid file, defaults to a random
temporary file.
--queue <size> Set listen queue size, defaults to
SOMAXCONN.
--reload Automatically reload application when the
source code changes.
--requests <number> Set maximum number of requests a worker
process is allowed to handle, not used by
default.
--servers <number> Set maximum number of children, defaults to
100.
--start <number> Set number of children to spawn at startup,
defaults to 5.
--user <name> Set user name for children.
EOF

# Dear Mr. President, there are too many states nowadays.
Expand All @@ -64,17 +70,19 @@ sub run {
'idle=i' => sub { $daemon->idle_timeout($_[1]) },
'interval=i' => sub { $daemon->cleanup_interval($_[1]) },
'keepalive=i' => sub { $daemon->keep_alive_timeout($_[1]) },
'listen=s' => sub { $daemon->listen($_[1]) },
'lock=s' => sub { $daemon->lock_file($_[1]) },
'maxspare=i' => sub { $daemon->max_spare_servers($_[1]) },
'minspare=i' => sub { $daemon->min_spare_servers($_[1]) },
'pid=s' => sub { $daemon->pid_file($_[1]) },
'queue=i' => sub { $daemon->listen_queue_size($_[1]) },
reload => sub { $daemon->reload(1) },
'requests=i' => sub { $daemon->max_keep_alive_requests($_[1]) },
'servers=i' => sub { $daemon->max_servers($_[1]) },
'start=i' => sub { $daemon->start_servers($_[1]) },
'user=s' => sub { $daemon->user($_[1]) }
'keepaliverequests=i' =>
sub { $daemon->max_keep_alive_requests($_[1]) },
'listen=s' => sub { $daemon->listen($_[1]) },
'lock=s' => sub { $daemon->lock_file($_[1]) },
'maxspare=i' => sub { $daemon->max_spare_servers($_[1]) },
'minspare=i' => sub { $daemon->min_spare_servers($_[1]) },
'pid=s' => sub { $daemon->pid_file($_[1]) },
'queue=i' => sub { $daemon->listen_queue_size($_[1]) },
reload => sub { $daemon->reload(1) },
'requests=i' => sub { $daemon->max_requests($_[1]) },
'servers=i' => sub { $daemon->max_servers($_[1]) },
'start=i' => sub { $daemon->start_servers($_[1]) },
'user=s' => sub { $daemon->user($_[1]) }
);

# Daemonize
Expand Down
11 changes: 6 additions & 5 deletions lib/Mojo/IOLoop.pm
Expand Up @@ -383,9 +383,12 @@ sub _accept {

# Accept
my $socket = $listen->accept or return;
my $id = "$socket";

# Unlock callback
$self->_callback('unlock', $self->unlock_cb);

# Add connection
my $id = "$socket";
my $c = $self->{_cs}->{$id} = {
accepting => 1,
buffer => Mojo::ByteStream->new,
Expand All @@ -412,9 +415,6 @@ sub _accept {
my $cb = $self->{_listen}->{$listen}->{cb};
$self->_event('accept', $cb, $id) if $cb;

# Unlock callback
$self->_callback('unlock', $self->unlock_cb);

# Remove listen sockets
$listen = $self->{_listen} || {};
my $loop = $self->{_loop};
Expand Down Expand Up @@ -683,11 +683,12 @@ sub _prepare {

# Nothing to do
my $listen = $self->{_listen} || {};
return delete $self->{_running}
delete $self->{_running}
unless keys %{$self->{_cs}}
|| $self->{_listening}
|| ($self->max_connections > 0 && keys %$listen);

return 1 unless $self->{_running};
return;
}

Expand Down
23 changes: 21 additions & 2 deletions lib/Mojo/Server/Daemon.pm
Expand Up @@ -16,7 +16,8 @@ use Mojo::IOLoop;
use Scalar::Util 'weaken';
use Sys::Hostname 'hostname';

__PACKAGE__->attr([qw/group listen listen_queue_size silent user/]);
__PACKAGE__->attr(
[qw/group listen listen_queue_size max_requests silent user/]);
__PACKAGE__->attr(ioloop => sub { Mojo::IOLoop->singleton });
__PACKAGE__->attr(keep_alive_timeout => 15);
__PACKAGE__->attr(
Expand Down Expand Up @@ -243,8 +244,18 @@ sub _build_tx {
$tx->upgrade_cb(sub { $self->_upgrade($id, @_) });

# New request on the connection
$c->{requests} ||= 0;
$c->{requests}++;

# Request limit
if (my $max = $self->max_requests) {
$self->{_requests} ||= 0;
if (++$self->{_requests} >= $max) {
$self->max_keep_alive_requests(1);
$self->ioloop->max_connections(0);
}
}

# Kept alive if we have more than one request on the connection
$tx->kept_alive(1) if $c->{requests} > 1;

Expand Down Expand Up @@ -350,7 +361,7 @@ sub _read {
my $tx = $c->{transaction} || $c->{websocket};

# New transaction
$tx = $c->{transaction} = $self->_build_tx($id) unless $tx;
$tx = $c->{transaction} = $self->_build_tx($id, $c) unless $tx;

# Read
$tx->server_read($chunk);
Expand Down Expand Up @@ -538,6 +549,14 @@ Maximum number of parallel client connections, defaults to C<1000>.
Maximum number of keep alive requests per connection, defaults to C<100>.
=head2 C<max_requests>
my $max_requests = $daemon->max_requests;
$daemon = $daemon->max_requests(1);
Maximum number of requests the daemon is allowed to handle, not used by
default.
=head2 C<pid_file>
my $pid_file = $daemon->pid_file;
Expand Down
19 changes: 14 additions & 5 deletions lib/Mojo/Server/Daemon/Prefork.pm
Expand Up @@ -18,6 +18,7 @@ use constant DEBUG => $ENV{MOJO_SERVER_DEBUG} || 0;
__PACKAGE__->attr(cleanup_interval => 15);
__PACKAGE__->attr(idle_timeout => 30);
__PACKAGE__->attr(max_clients => 1);
__PACKAGE__->attr(max_requests => 1000);
__PACKAGE__->attr(max_servers => 100);
__PACKAGE__->attr(max_spare_servers => 10);
__PACKAGE__->attr([qw/min_spare_servers start_servers/] => 5);
Expand Down Expand Up @@ -313,16 +314,16 @@ sub _spawn_child {

# Parent will send a HUP signal when there are too many children idle
my $done = 0;
$SIG{HUP} = sub {
$self->ioloop->max_connections(0);
$done++;
};
$SIG{HUP} = sub { $self->ioloop->max_connections(0) };

# User and group
$self->setuidgid;

# Spin
while (!$done) { $self->child }
while (!$done) {
$self->child;
$done++ if $self->ioloop->max_connections <= 0;
}

# Done
$self->child_status('done');
Expand Down Expand Up @@ -385,6 +386,14 @@ Timeout for workers to be idle in seconds, defaults to C<30>.
Maximum number of parallel client connections handled by worker, defaults to
C<1>.
=head2 C<max_requests>
my $max_requests = $daemon->max_requests;
$daemon = $daemon->max_requests(1);
Maximum number of requests a worker process is allowed to handle, defaults to
C<1000>.
=head2 C<max_servers>
my $max_servers = $daemon->max_servers;
Expand Down
2 changes: 1 addition & 1 deletion lib/Mojo/Server/FastCGI.pm
Expand Up @@ -23,7 +23,7 @@ my %ROLE_NUMBERS;
}
}

#Types
# Types
my @TYPES = qw/
BEGIN_REQUEST
ABORT_REQUEST
Expand Down

0 comments on commit 83853f3

Please sign in to comment.