Use SOMAXCONN which makes connections MUCH happier on high load servers
git-svn-id: https://svn.perl.org/qpsmtpd/branches/high_perf@421 958fd67b-6ff1-0310-b445-bb7760255be9
This commit is contained in:
parent
62aebd2a3e
commit
9432e1bac1
36
qpsmtpd
36
qpsmtpd
@ -27,7 +27,7 @@ $|++;
|
|||||||
# For debugging
|
# For debugging
|
||||||
# $SIG{USR1} = sub { Carp::confess("USR1") };
|
# $SIG{USR1} = sub { Carp::confess("USR1") };
|
||||||
|
|
||||||
use Socket qw(IPPROTO_TCP SO_KEEPALIVE TCP_NODELAY SOL_SOCKET);
|
use Socket qw(SOMAXCONN IPPROTO_TCP SO_KEEPALIVE TCP_NODELAY SOL_SOCKET);
|
||||||
|
|
||||||
$SIG{'PIPE'} = "IGNORE"; # handled manually
|
$SIG{'PIPE'} = "IGNORE"; # handled manually
|
||||||
|
|
||||||
@ -207,7 +207,7 @@ sub run_as_server {
|
|||||||
Proto => IPPROTO_TCP,
|
Proto => IPPROTO_TCP,
|
||||||
Blocking => 0,
|
Blocking => 0,
|
||||||
Reuse => 1,
|
Reuse => 1,
|
||||||
Listen => 10 )
|
Listen => SOMAXCONN )
|
||||||
or die "Error creating server $LOCALADDR:$PORT : $@\n";
|
or die "Error creating server $LOCALADDR:$PORT : $@\n";
|
||||||
|
|
||||||
IO::Handle::blocking($SERVER, 0);
|
IO::Handle::blocking($SERVER, 0);
|
||||||
@ -289,18 +289,8 @@ sub config_handler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
# TODO:
|
|
||||||
# - Make number of accepts() we do dependant on whether MAXCONNIP is set
|
|
||||||
|
|
||||||
# Accept all new connections
|
# Accept all new connections
|
||||||
sub accept_handler {
|
sub accept_handler {
|
||||||
my $max = $MAXCONNIP ? 100 : 1000;
|
|
||||||
for (1 .. $max) {
|
|
||||||
last if ! _accept_handler();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _accept_handler {
|
|
||||||
my $running;
|
my $running;
|
||||||
if( $LineMode ) {
|
if( $LineMode ) {
|
||||||
$running = scalar keys %childstatus;
|
$running = scalar keys %childstatus;
|
||||||
@ -309,12 +299,22 @@ sub _accept_handler {
|
|||||||
my $descriptors = Danga::Client->DescriptorMap;
|
my $descriptors = Danga::Client->DescriptorMap;
|
||||||
$running = scalar keys %$descriptors;
|
$running = scalar keys %$descriptors;
|
||||||
}
|
}
|
||||||
if ($running >= $MAXCONN) {
|
|
||||||
::log(LOGINFO,"Too many connections: $running >= $MAXCONN.");
|
my $max = $MAXCONNIP ? 100 : 1000;
|
||||||
return;
|
|
||||||
|
for (1 .. $max) {
|
||||||
|
if ($running >= $MAXCONN) {
|
||||||
|
::log(LOGINFO,"Too many connections: $running >= $MAXCONN.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$running++;
|
||||||
|
last if ! _accept_handler($running);
|
||||||
}
|
}
|
||||||
++$running if $LineMode; # count self
|
}
|
||||||
|
|
||||||
|
sub _accept_handler {
|
||||||
|
my $running = shift;
|
||||||
|
|
||||||
my $csock = $SERVER->accept();
|
my $csock = $SERVER->accept();
|
||||||
if (!$csock) {
|
if (!$csock) {
|
||||||
# warn("accept() failed: $!");
|
# warn("accept() failed: $!");
|
||||||
@ -331,7 +331,6 @@ sub _accept_handler {
|
|||||||
if (!$LineMode) {
|
if (!$LineMode) {
|
||||||
# multiplex mode
|
# multiplex mode
|
||||||
my $client = Qpsmtpd::PollServer->new($csock);
|
my $client = Qpsmtpd::PollServer->new($csock);
|
||||||
my $rem_ip = $client->peer_ip_string;
|
|
||||||
|
|
||||||
if ($PAUSED) {
|
if ($PAUSED) {
|
||||||
$client->write("451 Sorry, this server is currently paused\r\n");
|
$client->write("451 Sorry, this server is currently paused\r\n");
|
||||||
@ -341,7 +340,8 @@ sub _accept_handler {
|
|||||||
|
|
||||||
if ($MAXCONNIP) {
|
if ($MAXCONNIP) {
|
||||||
my $num_conn = 1; # seed with current value
|
my $num_conn = 1; # seed with current value
|
||||||
|
my $rem_ip = $client->peer_ip_string;
|
||||||
|
|
||||||
# If we for-loop directly over values %childstatus, a SIGCHLD
|
# If we for-loop directly over values %childstatus, a SIGCHLD
|
||||||
# can call REAPER and slip $rip out from under us. Causes
|
# can call REAPER and slip $rip out from under us. Causes
|
||||||
# "Use of freed value in iteration" under perl 5.8.4.
|
# "Use of freed value in iteration" under perl 5.8.4.
|
||||||
|
Loading…
Reference in New Issue
Block a user