如何在mod_perl上使用线程/多线程

kzmpq1sx  于 2022-11-15  发布在  Perl
关注(0)|答案(2)|浏览(178)

下面的代码在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没有发送任何数据。奇怪的是,如果我通过命令行执行脚本,它工作正常。

dkqlctbz

dkqlctbz1#

那么线程真的不能与mod_perl一起工作吗?
我还没有研究线程是否能与mod_perl2一起工作。请记住,mod_perl的要点是在Apache进程中运行一组持久的Perl解释器。
还要记住,Apache可以杀死需要很长时间才能响应的CGI脚本。现在,添加一组线程,这些线程是在Apache中的某个持久Perl进程中管理的,随时可能死亡。我希望很容易理解为什么人们的第一React是“好主意!”我从来没有想到这是我在CGI编程中遇到的任何问题的解决方案。
你能做什么或不能做什么在很大程度上取决于你选择的MPM以及你使用的httpdperl是如何编译的等等。
你需要解释为什么你认为你需要线程。你试图解决的问题是什么,在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下的线程编码问题。
另一个问题是“全局”变量只对创建它们的解释器全局。在同一进程中运行的多个线程之间可以共享变量。有关更多信息,请参阅:共享变量。

bxgwgixi

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要高。我们知道人们说它很老,但是它运行得很好很稳定,可能比其他任何语言都支持更多的操作系统,它就是这么工作的。

相关问题