在Java Web应用程序中,通常会产生线程来处理Web请求。我指的是应用程序代码,而不是容器的线程来接受传入的客户端连接。
在脚本语言中,例如Perl或Python,我的理解是,使用多处理范例(fork进程)比多线程处理(fork线程)要频繁得多。
我个人发现分叉进程,而不是Web服务器应用程序代码中的线程“怪异”和更重。
我正确吗?在这些框架中的Web处理过程中是否会分叉进程?在脚本化Web应用程序中首选分叉进程(而不是分叉线程)?
回答
Perl线程真的很重(请参阅How do I reduce memory consumption when using many threads in Perl?)。从我读的Python中的线程受到全局解释器锁的阻碍。 Java中的线程似乎更轻量化,但不像Linux中的操作系统线程那么轻量级。
如果你想在Perl中进行繁重的网络连接,你不要使用线程,而是使用类似于AnyEvent或POE的基于事件的编程,类似于具有Twisted框架的Python。有几个基于这些框架的Web服务器。 Java也有NIO框架,甚至在C现代快速Web服务器(如nginx)中使用基于事件的编程,而不是线程或进程。
我不知道任何常见的Web服务器,它分叉处理请求。如果他们完全岔开,他们使用预分叉模型,例如,他们预先派生了大量的工作进程(或者工作线程,如果他们使用线程而不是进程),并且如果有新的请求进入,则由现有工作人员处理。这比仅使用非常简单的服务器的请求式分支模型花费少得多。具有基于事件的处理的服务器也可能会分叉,但通常仅用于有效使用多个CPU(例如每个CPU一个进程)。
通过预分叉Web服务器,Web应用程序通常根本不分叉,只是使用当前进程。基于事件的Web服务器通常只能在内部和快速处理静态内容,因为它们通过FCGI等接口连接到其他过程(通常是预分配)的较慢的动态内容。这节省了资源,因为对于普通的网页,大多数请求都是针对静态内容的。
在Web应用程序中可能仍然存在分叉的原因。这是,如果您需要在后台执行一些工作(如调整上传的图像大小),而页面已完成并且内容应发送给用户。但即使在这种情况下,它的规模也要好得多,才能拥有一个专门的进程/线程来完成这项工作,并且只需要完成任务。
至于创建一个线程与一个进程的性能:一个进程的叉是在Unix/Linux(但不是在Windows中)便宜,因为它简单地克隆现有的进程结构并标记所有共享内存页面例如最初的所有页面)作为写入时拷贝。只有当新进程有效时,才会复制已更改的内存页面(这是昂贵的部分)。创建线程的代价在编程语言和操作系统之间差别很大,并不需要比创建新进程更快。
如果使用不当,Perl线程真的很重*。流程同样如此。 – ikegami
在Perl中创建线程和那里的内存使用情况在其他语言的线程中花费要高得多,因为整个解释器包含。所有未明确共享的东西都被克隆。比使用支持线程编译的Perl支付约15%的性能损失。但是,只要知道这些缺点,线程就可以以这些缺点无关紧要的方式使用(如使用工作池)。 –
@SteffenUllrich:答案中的内容是有用的和内容丰富的,但答案(除了一小部分)与我的问题无关。我的问题是关于处理传入客户端连接的线程池(在Java中可以使用阻塞方法或NIO)或基于事件的框架。这个问题仅仅集中在Web应用程序内需要完成的后端任务**,日志数据在一个单独的线程比框架客户端连接线程等 – Jim
- 1. Perl脚本,使用分叉或线程?
- 2. 分叉进程
- 3. 分叉子进程
- 4. 初始化脚本不会“停止”分叉C程序
- 5. 分叉在Python子进程下的多个应用程序
- 6. 进程分叉,子进程等[Java]
- 7. 与分叉进程混淆?
- 8. longjmp从分叉进程
- 9. 调用在后台线程/进程的功能(分叉)
- 10. 无法在分叉进程中设置OpenMP线程关联
- 11. 运行分叉PHP应用程序
- 12. Flex:交叉分辨率应用程序
- 13. 如何在shell脚本中从分叉子进程获取进程ID(pid)
- 14. 防止在子进程中分叉
- 15. 在分叉进程中嵌入Mojolicious :: Server
- 16. 在django视图中分叉进程
- 17. 如何在python/django中分叉进程?
- 18. 分叉进程的执行顺序
- 19. 在子进程中使用红宝石杀死分叉进程
- 20. 为分叉进程重新分配STDOUT
- 21. Linux守护进程不分叉?
- 22. 分叉进程找不到模块
- 23. 线程在分叉时未被复制?
- 24. ActiveRecord在分叉/线程应用程序中运行时无法重新连接?
- 25. 用Perl分叉进程输出
- 26. 如何用电子分叉子进程
- 27. C++进程中空/动态分叉
- 28. 处理分叉进程中的异常
- 29. 在加载TensorFlow后分叉python进程
- 30. 分叉的子进程挂在node.js
“在Java Web应用程序中,通常会产生线程来处理Web请求。”你是认真的吗?这到底是谁呢? –
@MikeBaranczak:我不是在谈论http线程。我正在谈论后端操作。通常使用线程或线程池。例子将是一个后台线程,例如,记录与当前请求相关的内容(不会阻止它)或在后端发送邮件等。 – Jim
好的,谢谢澄清。分叉和线程之间的选择取决于操作系统,以及父母和孩子之间需要多少互动。请参阅:http://stackoverflow.com/questions/16354460/forking-vs-threading –