Chinaunix

标题: 用Perl如何实现高效稳定的Socket Server? [打印本页]

作者: duketang    时间: 2005-11-18 19:09
标题: 用Perl如何实现高效稳定的Socket Server?
在运行一段时间后 进程就会死掉

#!/usr/bin/perl
use strict;
use IO::Socket;
my $server = IO::Socket::INET->new
(
        LocalPort =>2008,
        Type      =>SOCK_STREAM,
        Reuse     =>1,
        Listen    =>SOMAXCONN
)or die "Cound not create server!n";
my $client;
my $child_pid;
my $line;
while($client = $server->accept())
{
        unless (defined($child_pid=fork())) {die "Cound not create fork!n"};
        if($child_pid)
        {
                while($line=<$client>)
                {
                        print $line;
                }
        }else{
                while($line=<>)
                {
                        print $client $line;
                }
        }
}
作者: 兰花仙子    时间: 2005-11-18 19:15
原帖由 duketang 于 2005-11-18 19:09 发表
在运行一段时间后 进程就会死掉

#!/usr/bin/perl
use strict;
use IO::Socket;
my $server = IO::Socket::INET->new
(
        LocalPort =>2008,
        Type      =>SOCK_STREAM,
         ...



while($client = $server->accept())
这里你这样写,不死掉才怪呢。

另外,要调用waitpid来回收child process。只创建,不回收,会对OS很不利的。
作者: flw    时间: 2005-11-18 20:27
Please use POE::Component::Server::TCP, it maybe a good choice for you.

  1. use POE;
  2. use POE::Component::Server::TCP;

  3. POE::Component::Server::TCP->new(
  4.     Port            => 9999,
  5.     ClientConnected => sub {
  6.                             $_[HEAP]->{client}->put( "Welcome!" );
  7.                         },
  8.     ClientInput     => sub {
  9.                             my $msg = $_[ARG0];
  10.                             $_[HEAP]->{client}->put( "Your said: $msg" );
  11.                         },
  12. );

  13. POE::Kernel->run();
复制代码


For more information, please visit http://poe.perl.org/

[ 本帖最后由 flw 于 2005-11-18 20:42 编辑 ]
作者: freeand    时间: 2005-11-18 22:22
对啊,有没有用perl写的比较成熟的成品啊。。。
作者: duketang    时间: 2005-11-19 18:18
修改后 可以了
#!/usr/bin/perl
use strict;
use IO::Socket;
use POSIX 'WNOHANG';
use constant PORT => 2008;

my $quit        =       0;
$SIG{CHLD}      = sub   {while(waitpid(-1,WNOHANG)>0){}};
$SIG{INT}       = sub   {$quit++};
my $i=1;
my $server_socket       =       IO::Socket::INET->new
(
        LocalPort       =>      PORT,
        Listen          =>      SOMAXCONN,
        Proto                   =>      'tcp',
        Reuse                   =>      1,
        Timeout         =>      60
) or die "ERROR!n";
while(!$quit)
{
        next unless my $connection = $server_socket->accept;
        defined(my $child = fork()) or die "error!n";
        if($child == 0)
        {
                print "Line ".$i."   ";
                $server_socket->close;
                repeat_server($connection);
                exit 0;
        }

        $connection->close;
        $i++;
}

sub repeat_server
{
        my $sock = shift;
        while(my $line = <$sock>)
        {
                print $line;
        }
}
作者: duketang    时间: 2005-11-19 18:33
项这样的 每秒钟最多能承受多少连接?
作者: 兰花仙子    时间: 2005-11-19 18:43
原帖由 duketang 于 2005-11-19 18:33 发表
项这样的 每秒钟最多能承受多少连接?


做个压力测试不就知道了嘛,几百个连接没问题的。
当然,还得取决于你的主机配置。
作者: duketang    时间: 2005-11-19 18:48
我现在最大只能达到八百多 实际环境中
如果在这段程序中实现对多个数据库发送query速度会慢多少?
数据库连接在前面初始化好 只在repeat_server中进行发送query的操作
没有检索 只是update delete ..等不需要数据返回的操作
作者: 兰花仙子    时间: 2005-11-19 20:01
原帖由 duketang 于 2005-11-19 18:48 发表
我现在最大只能达到八百多 实际环境中
如果在这段程序中实现对多个数据库发送query速度会慢多少?
数据库连接在前面初始化好 只在repeat_server中进行发送query的操作
没有检索 只是update delete ..等不需要 ...


同时连接800多相当不错了,可别对perl socket期望太高。
数据库查询不是你的程序的性能瓶颈,如果数据库本身性能不错的话。
作者: freeand    时间: 2005-11-19 21:36
原帖由 兰花仙子 于 2005-11-19 20:01 发表


同时连接800多相当不错了,可别对perl socket期望太高。


为什么这样说?
没希望了?
作者: 兰花仙子    时间: 2005-11-19 21:40
原帖由 freeand 于 2005-11-19 21:36 发表


为什么这样说?
没希望了?


实际就是这样的,你可以自己试试。
如果能达到上千的同时连接,并且性能稳定,那请告诉偶一声。
btw:如果你的网络应用规模那么大,照你的意思是同时连接数过千,那为什么不用C来实现?
作者: duketang    时间: 2005-11-19 21:51
我是想做mysql同步 所以在PHP中调用数据库类的时候针对update insert replace语句建立socket连接 把query 发到这个sock_svr
由sock_svr分发到各个mysql server上都是短连接 时间都不超过1秒 Perl的sock承受不了过多连接么?我刚才看了一下占用 进程最多占用5%CPU资源
作者: 兰花仙子    时间: 2005-11-19 22:07
原帖由 duketang 于 2005-11-19 21:51 发表
我是想做mysql同步 所以在PHP中调用数据库类的时候针对update insert replace语句建立socket连接 把query 发到这个sock_svr
由sock_svr分发到各个mysql server上都是短连接 时间都不超过1秒 Perl的sock承受不了过 ...



你自己试试嘛,偶说能支持几千也没用呀。
Perl的Socket,fork等都是基于底层的C库封装的,你这里只是简单的利用了它们。要想实现高性能的svr,也不是这几十行code就可以的呀。在小压力环境下,你的子进程及Socket实现良好。若压力大时,Socket svr的子进程会出现收不回的情况,并交互影响,结果是越来越多的子进程累计收不回,导致system resource耗光而让OS Down掉。偶经历过这种情况,你可以自己test下。
作者: 兰花仙子    时间: 2005-11-19 22:09
原帖由 duketang 于 2005-11-19 21:51 发表
我是想做mysql同步 所以在PHP中调用数据库类的时候针对update insert replace语句建立socket连接 把query 发到这个sock_svr
由sock_svr分发到各个mysql server上都是短连接 时间都不超过1秒 Perl的sock承受不了过 ...


另外,要实现你的目的,也用不着自己写socket代理呀;有很多成熟的db cache proxy的,例如Apache:: DBI
作者: duketang    时间: 2005-11-19 22:49
apache :: DBI 是什么东西? 是perl的模块?
作者: 兰花仙子    时间: 2005-11-19 23:50
原帖由 duketang 于 2005-11-19 22:49 发表
apache :: DBI 是什么东西? 是perl的模块?


Seeing here for something about Apache:: DBI:

http://perl.apache.org/docs/1.0/ ... database_connection
作者: duketang    时间: 2005-11-20 13:54
这个我看了下描述好像只是数据库连接的类?

已经改用c++写了~ 在小负荷的情况下 就已经比perl强不少
作者: apile    时间: 2005-11-21 08:56
用socket的话..可以在inetd.conf中..要把nowait改成wait...
这样子不会每次有新的request来都要fork新的process...
同一个server可以wait几分钟後,再die....
这样子可以多接收点request..

如果是自己写的stand alone daemon...可以先prefork一些server process..等在那边......
这样子....效能会更快...像apache httpd一样...
不管C或perl都一样....
给你叁考吧...

[ 本帖最后由 apile 于 2005-11-21 08:57 编辑 ]




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2