基于Apache preforking的多进程共享套接字中的accept()函数

16

我正在开发一些模仿Apache MPM prefork服务器的Python代码。我更擅长应用程序开发而不是网络编程,并且距离我阅读Stevens已经过去了10年,所以我正试图提高理解这段代码的能力。

我找到了Sander Temme关于Apache预分配代码如何工作的简短描述

父进程通常作为root用户运行,绑定到一个socket上(通常是端口80或443)。它会生成子进程,子进程继承打开的文件描述符并将uid和gid更改为非特权用户和组。子进程构建监听器文件描述符的pollset(如果有多个监听器)并监视其中的活动情况。如果发现有活动,子进程就在活动的socket上调用accept()并处理连接。完成后,子进程返回监视pollset(或监听器文件描述符)状态。

由于有多个活跃的子进程并且它们都继承了相同的socket文件描述符,它们将监视相同的pollset。一个accept mutex允许只有一个子进程实际上监视pollset,在找到活动的socket后,它将解锁mutex,以便下一个子进程可以开始监视pollset。如果只有一个监听器,则不使用该accept mutex,所有子进程都将在accept()中挂起。

这基本上就是我正在研究的代码工作方式,但我不理解其中的一些内容。

1)“child”和“listener”之间有什么区别?我认为每个子进程都是一个监听器,在我看的代码中也是如此,但是在Temme的描述中可以有“单个监听器”和“子进程”。什么情况下子进程会有多个监听器?

2) (与1相关)这是进程级互斥锁还是系统级互斥锁?说起来,为什么需要互斥锁?accept(2)难道不会在所有监听器上自己进行互斥锁操作吗?我的研究表明我确实需要一个互斥锁,而且该互斥锁必须跨整个系统。(flock、semaphore等)

Temme接着说:

子进程在共享内存区域(记分牌)中记录它们最后提供服务的时间。空闲的子进程可能会被父进程杀死,以满足MaxSpareServers的要求。如果空闲的子进程太少,父进程将生成更多的子进程以满足MinSpareServers。

3) 是否有这种实现的好参考代码(最好用Python)?我发现Perl的Net::Server::Prefork使用管道而不是记分牌的共享内存。我发现了Randal Schwartz的一篇文章,但它只做了预分叉而没有做记分牌。

Perl Cookbook的预分叉示例没有在select周围进行任何形式的锁定,而Chris Siebenmann的Python示例说它是基于Apache的,但使用成对的套接字来进行记分牌,而不是共享内存,并使用这些套接字进行控制,包括给定子进程的“接受”控制。这完全不符合Apache的描述。


你是否在使用 mod_wsgi 作为 Apache 和 Python 之间的接口?如果是,它应该会为你处理所有这些问题。 - S.Lott
这是一个纯Python预派生WSGI服务器。我的客户想要一个轻量级的解决方案,适用于不想要Apache和mod_wsgi或等效物的地方。我找到的唯一的Python-only WSGI服务器是Spawning,它需要eventlet。...虽然现在我发现flup有一个像Siebenmann那样使用管道而不是共享内存来实现记分牌的实现,并且对我的客户具有可接受的许可证。 - Andrew Dalke
1个回答

16
关于(1),"listener"仅是指存在用于接受连接的套接字的参考。由于Apache可以同时在多个套接字上接受连接,例如80/443,则存在多个监听套接字。当子进程到来时,每个子进程都需要侦听所有这些套接字。由于accept()只能一次在一个套接字上进行,因此它在poll/select之前执行,以便知道在哪个监听套接字上应执行accept。
关于(2),这是一个全局或跨进程互斥锁。也就是说,锁定它的一个进程将阻止其他进程试图获取相同的锁。虽然accept()技术上会串行化进程,但存在多个监听套接字意味着您不能依靠它,因为您不知道应该在哪个套接字上执行accept。即使只有一个侦听套接字,使用accept互斥锁的原因也是,如果有大量处理请求的进程,则如果操作系统唤醒所有进程以查看哪个进程accept()返回,则可能会非常昂贵。由于Apache在prefork模式下可能具有100多个进程,这可能会引起问题。
因此,如果您只有一个侦听套接字并且知道只有少数进程想要执行accept()调用,则可能可以取消跨进程接受互斥锁。

谢谢Graham!我完全没有想到可能会有多个监听器,以及它如何影响一切。现在我的理解更加清晰了,无论是代码为什么能够工作,还是为什么看起来好像没有工作。 - Andrew Dalke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接