2

我在一个小项目中工作,我需要从一个源(文件、套接字等)读取一些东西,在许多客户端中处理和写入(每个新客户端都不同)。

我正在使用 select 来多路复用 I/O。

如果我可以读取源,我将存储在内部缓冲区中,处理并写入许多输出缓冲区(每个客户端一个)。如果我可以写,我只写缓冲区。听起来不错。

但是我如何才能为大量用户扩展它呢?我正在考虑使用 fork 并设置每个进程的 x 连接。我真的不知道这是一个好方法还是更好的预分叉或使用不同的端口并使用一些负载平衡但是现在我不清楚我该如何处理 fork + select

例如,如果我在每个进程中使用 100 个客户端,则在第 101 个客户端中,我将分叉,但内存中仍然有旧的 select 和 100 个套接字客户端。我可以清理“旧”选择并开始一个新选择,但这很奇怪。我不知道我的策略是否足够好。

4

4 回答 4

2

通常这是用“prefork”技术制作的。这是这样工作的:

1) 创建监听套接字

2)fork()让N个工人

3)每个工人开始accept()客户(大多数免费工人将接受这份工作);同时“父”进程变为“经理”和waitpid()他的子进程,如果“工人”的数量 < N 则分叉

但是这样你就不能在“工人”之间发送数据(就像你最初在其他进程中使用第 101 个客户端的情况一样),所以这个设计可能不适合你的需求。在这种情况下,我更喜欢使用AnyEvent CPAN 模块。这使您可以一次异步处理更多的客户端,因为它使用 epoll/kqueue 进行多路复用,并且可以在一个信号进程上扩展到数千个连接(如果您的脚本不是 CPU 密集型的)。

于 2012-11-29T14:55:36.107 回答
1

如果您不反对围绕框架编写应用程序,我可以建议在 CPAN 上使用相当古老且屡获殊荣的多任务/网络框架POE

它基本上提供了一个内核和事件循环select(这过于简单化了)。你写回调。x事件发生时做e之类的事情。它非常适合同时读取/写入多个源,无论它们是套接字、文件还是终端。这需要一些时间来适应,但它非常有用。有很多很好的例子

例如,如果您想通过预先分叉一个进程池来扩展,POE 提供了一些可以轻松管理的东西:http://metacpan.org/pod/POE ::Wheel::Run

如果你需要一个处理并发客户端的 TCP 服务器,这里是:http ://metacpan.org/pod/POE::Component::Server::TCP

请注意,它使用线程;它是一种使用事件循环和回调的协作多任务处理形式。如果您需要为每个请求执行的处理只需要微不足道的时间,那么这就是您所需要的,但是如果您想将一些可能阻塞的工作委托给预分叉进程池,那么这也很容易,使用POE::Wheel::Run.

于 2012-11-29T15:21:18.043 回答
0

通常的方法是预先分叉一些工作进程,然后将新接受的客户端套接字的文件描述符传递给它们,比如以某种循环方式,以便在 UNIX 域套接字上进行进一步处理。

于 2012-11-29T14:55:24.393 回答
0

我不太确定我是否正确理解了您的要求,但如果您从一个来源获取输入并将输出复制到多个来源,您可能需要查看诸如 ZeroMQ 之类的 PubSub 系统。请参阅http://zeromq.org/https://metacpan.org/module/ZMQ

这假定您不受客户端和服务器之间的特定协议的约束。

于 2012-11-29T15:18:59.537 回答