Permalink
Browse files

Added ControlFreak support. Reworked wrapper/chain callback interface.

  • Loading branch information...
1 parent e4ae7eb commit 3cc05900dd805ce5e745a425f4663259c55c7344 @miyagawa committed Jan 12, 2010
Showing with 124 additions and 12 deletions.
  1. +13 −2 README
  2. +64 −0 bin/nomo-cfk
  3. +25 −2 lib/Nomo.pm
  4. +1 −0 lib/Nomo/Engine/HTTPServer.pm
  5. +1 −1 lib/Nomo/Engine/HTTPServer/Prefork.pm
  6. +6 −0 lib/Nomo/Engine/HTTPServer/ServerStarter.pm
  7. +14 −7 lib/Nomo/Loader.pm
View
@@ -12,21 +12,32 @@ DESCRIPTION
Nomo is a collection of unique Web servers, that are:
High Performance
- Heavily uses XS to use C extensions to parse XS headers and use
+ Heavily uses XS to use C extensions to parse HTTP headers and use
sendfile(2) to serve static files if available.
Preforking
Runs servers preforked like most high performance UNIX servers do.
This means your applications are preloaded to be copy-on-write
friendly.
+ It also means your application can be blocking, and load-balancing
+ is handled by kernels. No requests piled up behind busy workers.
+
Superdaemon aware
Automatically detect superdaemon such as Server::Starter and
- ControlFreak for hot-deploy and UNIX socket sharing.
+ ControlFreak to benefit from features such as hot deploy, graceful
+ restarts and sharing UNIX Domain sockets.
PSGI compatible
Can run any PSGI applications and frameworks.
+ Features that are planned but not implemented are:
+
+ Reaping dead workers
+ Logrotate via signals
+ Dynamic adjustment of Worker processes
+ Perl DSL configuration
+
NOMO?
The name Nomo is taken from the baseball player <Hideo Nomo>, who is a
great starter, famous for his forkball and whose nickname is Tornado.
View
@@ -0,0 +1,64 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+use AnyEvent;
+use Plack::Util;
+use ControlFreak::Proxy::Process;
+use Nomo::Loader;
+
+my $app_psgi = $ARGV[0] || "app.psgi";
+my $app = Plack::Util::load_psgi($app_psgi);
+
+my $cfd = $ENV{_CFK_COMMAND_FD} or die "no command fd";
+my $sfd = $ENV{_CFK_STATUS_FD} or die "no status fd";
+my $lfd = $ENV{_CFK_LOG_FD} or die "no log fd";
+
+open my $cfh, "<&=$cfd"
+ or die "Cannot open Command filehandle, is descriptor correct?";
+
+open my $sfh, ">>&=$sfd"
+ or die "Cannot open Status filehandle, is descriptor correct?";
+
+open my $lfh, ">>&=$lfd"
+ or die "Cannot open Status filehandle, is descriptor correct?";
+
+trap_sigs();
+
+my $sockets = ControlFreak::Proxy::Process->sockets_from_env;
+
+my $proxy = ControlFreak::Proxy::Process->new(
+ command_fh => $cfh,
+ status_fh => $sfh,
+ log_fh => $lfh,
+ sockets => $sockets,
+ svc_coderef => sub {
+ Nomo::Loader->new->run($app),
+ },
+);
+
+$proxy->{app} = $app;
+
+$proxy->log('out', "$0 proxy started");
+$proxy->run;
+
+sub trap_sigs {
+ $SIG{HUP} = $SIG{INT} = $SIG{TERM} = sub {
+ my $sig = shift;
+ if ($proxy) {
+ $proxy->log("err", "Got signal $sig");
+ $proxy->shutdown;
+ }
+ exit 0;
+ };
+ $SIG{__WARN__} = sub {
+ my $warn = shift || "";
+ $proxy->log("err", "warn $warn") if $proxy;
+ };
+ $SIG{__DIE__} = sub {
+ my $reason = shift || "";
+ return if $^S;
+ $proxy->log("err", "die $reason") if $proxy;
+ exit -1;
+ };
+}
View
@@ -31,7 +31,7 @@ Nomo is a collection of unique Web servers, that are:
=item High Performance
-Heavily uses XS to use C extensions to parse XS headers and use
+Heavily uses XS to use C extensions to parse HTTP headers and use
sendfile(2) to serve static files if available.
=item Preforking
@@ -40,17 +40,40 @@ Runs servers preforked like most high performance UNIX servers
do. This means your applications are preloaded to be copy-on-write
friendly.
+It also means your application can be blocking, and load-balancing is
+handled by kernels. No requests piled up behind busy workers.
+
=item Superdaemon aware
Automatically detect superdaemon such as Server::Starter and
-ControlFreak for hot-deploy and UNIX socket sharing.
+ControlFreak to benefit from features such as hot deploy, graceful
+restarts and sharing UNIX Domain sockets.
+
+=item UNIX only
+
+Optimized for UNIX for the best performance by avoiding weird Win32
+compatible code.
=item PSGI compatible
Can run any PSGI applications and frameworks.
=back
+Features that are planned but not implemented are:
+
+=over 4
+
+=item Reaping dead workers
+
+=item Logrotate via signals
+
+=item Dynamic adjustment of Worker processes
+
+=item Perl DSL configuration
+
+=back
+
=head1 NOMO?
The name Nomo is taken from the baseball player
@@ -1,6 +1,7 @@
package Nomo::Engine::HTTPServer;
use strict;
use Plack::Util;
+use HTTP::Parser::XS;
sub new {
my($class, %opts) = @_;
@@ -4,7 +4,7 @@ use strict;
sub wrap {
my($class, $cb, $opts) = @_;
$opts->{parent} = "HTTP::Server::PSGI::Prefork";
- $cb->(%$opts);
+ $cb->($opts);
}
1;
@@ -13,6 +13,12 @@ sub wrap {
$opts->{port} = $hostport;
}
+ $opts->{server_ready} = sub {
+ my $server = shift;
+ print STDERR ref($server),
+ ": Accepting connections at http://$server->{host}:$server->{port}/ (via Server::Starter socket $fd)\n";
+ } if $opts->{server_ready};
+
my $server = $cb->(%$opts);
$server->{listen_sock} = IO::Socket::INET->new(
View
@@ -14,25 +14,32 @@ sub new {
my $workers = $opts{max_workers} || 32;
my $server_class = Plack::Util::load_class($engine, "Nomo::Engine");
- my $server = sub { $server_class->new(@_) };
+ my $builder = sub { $server_class->new(%{$_[0]}) };
my @wrappers;
- push @wrappers, "Prefork" if $workers > 1;
- push @wrappers, "ServerStarter" if $ENV{SERVER_STARTER_PORT};
+ if ($ENV{CONTROL_FREAK_ENABLED}) {
+ $workers = 1;
+ push @wrappers, "ControlFreak";
+ } else {
+ push @wrappers, "Prefork" if $workers > 1;
+ push @wrappers, "ServerStarter" if $ENV{SERVER_STARTER_PORT};
+ }
for my $wrapper (@wrappers) {
my $wrapper_class = Plack::Util::load_class($wrapper, "Nomo::Engine::$engine");
- $server = build { $wrapper_class->wrap(@_) } $server, \%opts;
+ $builder = build { $wrapper_class->wrap(@_) } $builder, \%opts;
}
- bless { server => $server, opts => \%opts }, $class;
+ $opts{max_workers} = $workers;
+
+ my $server = $builder->(\%opts);
+ bless { server => $server }, $class;
}
sub run {
my($self, $app) = @_;
- my $server = $self->{server}->(%{$self->{opts}});
- $server->run($app);
+ $self->{server}->run($app);
}
1;

0 comments on commit 3cc0590

Please sign in to comment.