在Java web应用程序中,通常会产生处理web请求的线程。我指的是接受传入客户端连接的应用程序代码,而不是容器的线程。
在脚本语言中,例如Perl或Python,我的理解是最常使用多处理范例(分支进程)而不是多线程范例(分支线程)。
我个人发现,在web服务器应用程序代码中使用forking进程而不是线程是“奇怪的”,而且更加繁琐。
在这一点上我说得对吗?在这些框架中,在web处理过程中,forking过程是否正常?
发布于 2014-01-13 07:43:28
Perl线程非常繁重(参见How do I reduce memory consumption when using many threads in Perl?)。据我所知,python中的线程受到全局解释器锁的阻碍。Java中的线程似乎更轻量级,但没有Linux中的OS线程那么轻量级。
如果你想在Perl语言中进行大量的网络编程,你可以不使用线程,而是使用基于事件的编程,比如AnyEvent或POE,类似于具有Twisted框架的Python。有几个基于这些框架的web服务器。Java也有NIO框架,甚至在C语言中,像nginx这样的现代快速web服务器也使用基于事件的编程,而不是线程或进程。
我不知道任何常见的web服务器,它分叉处理一个请求。如果它们使用预先派生模型,例如,它们预先派生许多工作进程(如果它们使用线程而不是进程,则为工作线程),并且如果有新的请求进入,则由现有的工作进程之一来处理。这比仅使用非常简单的服务器的fork-on-request模型的开销要小得多。具有基于事件处理的服务器也可能分叉,但通常只是为了有效地利用多个CPU (例如,每个CPU一个进程)。
使用预先派生的web服务器,web应用程序通常根本不派生,而只是使用当前进程。基于事件的web服务器通常只在内部快速处理静态内容,对于速度较慢的动态内容,它们通过FCGI等接口连接到其他进程,这些进程通常是预先派生的。这节省了资源,因为对于普通的网页,大多数请求都是针对静态内容的。
可能仍然有理由在web应用程序中进行派生。这是,如果你需要在后台做一些工作(如调整上传图像的大小),而页面已经完成,内容应该发送给用户。但即使在这种情况下,它的伸缩性也要好得多,因为有一个专门的进程/线程来做这项工作,并且只向它提供任务。
至于创建线程与创建进程的性能:进程的分支在Unix/Linux (但不是windows)中是便宜的,因为它简单地克隆现有的进程结构,并将所有共享内存页面(例如,最初的所有页面)标记为写入时复制。只有当新进程工作时,更改的内存页才会被复制(这是开销较大的部分)。创建线程的成本在编程语言和操作系统之间差别很大,并且不需要比派生一个新进程更快。
https://stackoverflow.com/questions/21080712
复制相似问题