下面的代码在mod_cgi上运行良好,但在mod_perl上就不行了。代码在创建第一个线程时就崩溃了。关于如何在mod_perl上实现线程有什么想法吗?这真的可能吗?我错过了什么?
use strict;
use warnings;
use threads;
print "Content-type: text/html\n\n";
sub testthread{
my $value = shift;
print "<br>test - $value"
}
my @threads = ();
push(@threads, threads->new(\&testthread, 1));
push(@threads, threads->new(\&testthread, 2));
foreach (@threads) {
$_->join;
}
exit;
没有给出错误消息。我的网页/脚本只是停止并向浏览器提供以下错误:www.abcd.com页面不工作www.abcd.com没有发送任何数据。奇怪的是,如果我通过命令行执行脚本,它工作正常。
2条答案
按热度按时间dkqlctbz1#
那么线程真的不能与mod_perl一起工作吗?
我还没有研究线程是否能与
mod_perl2
一起工作。请记住,mod_perl
的要点是在Apache进程中运行一组持久的Perl解释器。还要记住,Apache可以杀死需要很长时间才能响应的CGI脚本。现在,添加一组线程,这些线程是在Apache中的某个持久Perl进程中管理的,随时可能死亡。我希望很容易理解为什么人们的第一React是“好主意!”我从来没有想到这是我在CGI编程中遇到的任何问题的解决方案。
你能做什么或不能做什么在很大程度上取决于你选择的MPM以及你使用的
httpd
和perl
是如何编译的等等。你需要解释为什么你认为你需要线程。你试图解决的问题是什么,在CGI script run under
mod_perl
中使用线程将如何帮助你解决它?请参见mod_perl文档:
线程支持
为了适应Apache 2.0线程体系结构(对于线程化MPM),mod_perl 2.0需要使用线程安全Perl解释器,也称为“
ithreads
“该机制可以在编译时启用,并确保每个Perl解释器使用其私有PerlInterpreter
结构来存储其符号表,堆栈和其他Perl运行时机制。当采用这种分离时,同一进程中的任意数量的线程都可以安全地并发回调到Perl中。当然,这要求每个线程都有自己的PerlInterpreter
对象,或者至少每个示例在任何给定时间仅被一个线程访问。第一代
mod_perl
只有一个PerlInterpreter,它由父进程构造,然后通过fork继承到子进程。mod_perl
2.0有可配置数量的PerlInterpreter
和两类解释器,父类和克隆类。父类类似于mod_perl
1.0中的解释器,其中在启动时创建的主解释器编译任何预加载的Perl代码。()函数。在请求时,父解释器仅用于生成更多克隆,因为克隆是实际处理请求的解释器。Perl注意只复制可变数据,这意味着不需要运行时锁定,并且诸如语法树之类的只读数据是从父对象共享的,这将减少总的mod_perl
存储器覆盖区。mod_perl不是默认地为每个线程创建一个
PerlInterpreter
,而是创建一个解释器池。池机制有助于大大减少内存使用。正如已经提到的,语法树在所有克隆的解释器之间共享。如果您的服务器正在处理多于mod_perl
的请求,PerlInterpreter
的数量比线程的数量要少,这将明显减少内存使用。当调用Perl子程序时,会在变量第一次使用时为其分配内存。以后使用变量时可能会分配更多的内存,例如,如果标量变量需要保存比以前更长的字符串,或者数组添加了新元素。作为优化,Perl会挂起这些分配,即使它们的值“超出了作用域”。mod_perl2.0可以更好地控制哪些PerlInterpreters
用于传入的请求。解释器存储在两个链表中,一个用于可用的解释器,另一个用于忙碌的解释器。当需要处理请求时,一个解释器被从可用列表的头部取出,并在完成后放回到同一列表的头部。这意味着,例如,如果您有10个解释器被配置为在启动时被克隆,但并发使用的解释器不超过5个,则这5个解释器继续重用Perl的分配,而另外5个解释器保持得小得多,但在需要时随时准备行动。池的各种属性可使用线程模式特定指令进行配置。
解释器池机制已被抽象为一个API,称为“tipool”,线程项目池。此池可用于管理任何数据结构,其中您希望拥有的线程数小于已配置的线程数。例如,基于tipool的
Apache::DBI
替换将允许重复使用同一进程的多个线程之间的数据库连接。线程环境问题
虽然
mod_perl
本身是线程安全的,但是您可能会遇到代码的线程安全问题。更多信息请参考mod_perl下的线程编码问题。另一个问题是“全局”变量只对创建它们的解释器全局。在同一进程中运行的多个线程之间可以共享变量。有关更多信息,请参阅:共享变量。
bxgwgixi2#
我们使用Apache事件多处理模块(MPM)和APACHE::DBI以及MySQL 5.7运行mod_perl,以处理大量用户登录和开始测验/考试的情况。
我们将Apache 2.4配置为从50个子进程开始,每个子进程运行100个线程,总共有5,000个线程可供请求使用。由于mod_perl也运行多线程,并且捆绑到Apache中(启动时),因此与其他语言相比,内存消耗最小。
我们将Apache设置为始终有3,500个可用线程,最多有200个子线程(20,000个线程)。子线程在处理10,000个请求后回收(以防内存泄漏)。当Apache每晚回收日志时,Apache会重新启动mod_perl和所有数据库连接,并再次启动5,000个可用线程。
对于mod_perl,我们从50个子进程开始,以匹配apache子进程,并且它还回收它的子进程。
在虚拟服务器指令中,我们有:
PerlInterpStart 50 PerlInterpMax备用磁盘50 PerlInterpMax 100
真实的的简单性带来了很高的可扩展性和稳定性以及低成本的硬件。而且它在Windows上也运行得很好。如果你的东西不能运行多线程,它只限于每个请求需要一个子程序(1:1的比例)而不是一个线程(1:100的比例)。每个子程序需要你的程序的一个示例来运行(除了Java?),所以内存消耗比使用mod_perl要高。我们知道人们说它很老,但是它运行得很好很稳定,可能比其他任何语言都支持更多的操作系统,它就是这么工作的。