multithreading - 如何通过一些约定使mod_perl解释器具有粘性?

标签 multithreading apache perl mod-perl

似乎mod_perl仅管理Perl interpreters per VHOST,是
有什么办法可以影响哪个克隆的解释器mod_perl
选择处理请求?我已经阅读了可配置文件
范围,并查看源代码中的“modperl_interp_select”和我
可以看到,如果一个请求已经有一个关联的解释器,那
一个由mod_perl选择。

else if (r) {
    if (is_subrequest && (scope == MP_INTERP_SCOPE_REQUEST)) {
[...]
    }
    else {
        p = r->pool;
        get_interp(p);
    }

我想在mod_perl选择一个
解释器处理请求,然后选择一个解释器
根据包含在其中的不同标准,将其自己分配给请求
请求。

但是我很难理解这样的处理程序是否可以存在于
全部,或者与请求有关的所有内容都已经被处理
选择的mod_perl解释器。

此外,我可以看到APR::Pool-API,但似乎没有提供
可以在当前池对象上设置一些用户数据的功能,
是mod_perl通过“get_interp”读取的内容。

有人可以帮我吗?谢谢!

关于背景:我在cgi-bin中有一个dir结构,如下所示:
cgi-bin
    software1
        customer1
            *.cgi
            *.pm
        customer2
            *.cgi
            *.pm
    software2
        customer1
            *.cgi
            *.pm
        customer2
            *.cgi
            *.pm

每个客户都使用该软件的私有(private)副本,并且该软件正在使用自己的软件,例如通过将一些特殊的客户端软件libs2加载到自己的Perl解释器中,customer1的software1可以与customer1的software2进行对话。为了使事情更复杂,软件2甚至可以使用svn:external将软件1的通用/公共(public)部分带入其自己的专用安装中。因此,我在一个VHOST中有很多具有相同Perl软件包的相同软件,而且我不能保证所有这些私有(private)安装始终具有相同的版本级别。

这是一个相当困惑的过程,但是众所周知,它可以在我们同一个Perl解释器中使用的规则下工作。

但是现在出现了mod_perl,根据需要克隆了解释器,并将其重用于其喜欢的cgi-bin的任何子目录中,在这种情况下事情将中断,因为突然间,解释器已经处理了customer1的software1,现在应该处理customer2的software2,使用通用的software1软件包,这些软件包已经由Perl解释器以前加载过,并且因为%INC而被使用,而不是专用于software2的私有(private)软件包,例如...

是的,有多种方法可以处理此问题,例如VHOST和persoftware或客户或任何其他子域,但我想通过使用mod_perl或Apache httpd提供的内容来检查保留一个VHOST和当前目录结构的不同方法。一种方法是,如果我可以告诉mod_perl始终对同一目录的请求使用相同的Perl解释器。这样mod_perl将创建它的解释器池,我将负责在每个目录中选择每个解释器。

最佳答案

到目前为止,我了解到,很难影响mod_perl关于选定解释器的决定。如果愿意的话,似乎需要在C级上真正修补mod_perl或为httpd提供一个自己的C处理程序,以作为在mod_perl之前运行的钩子(Hook)。最后,mod_perl只是httpd本身的处理程序的组合,因此可以在其前面放置一个做一些特殊的事情。这是否是一个明智的选择,是另一个问题,因为人们将不得不处理一些mod_perl内部组件,例如目前没有可用的解释器,最后我需要在 map 上放置一个 map 以供解释器及其相关目录进行处理。

最后,它并不是那么容易,我不想修补mod_perl或从低级C开始以获取httpd处理程序/ Hook 。

出于文档目的,我想提到两种可能的解决方法:

Perl线程池

在我的情况下,当前mod_perl方法的问题是它将Perl解释器克隆到C底层,并且由httpd池提供的线程运行,每个线程可以在任何给定时间运行任何解释器,除非尚未被任何人使用。另一个线程。通过这种方法,在不使用任何低级XS的情况下,似乎也无法访问Perl自身中的解释器,尤其是不可能使用Perl's Threads API管理解释器和线程,只是因为它不是Perl线程,而是由Perl执行的Perl解释器httpd线程。最后,两者的行为相同,因为在创建Perl线程期间,当前的解释器也将被克隆,并创建相关的OS线程。但是,在使用Perl的线程时,您会对共享数据等产生更大的影响。

因此,针对我当前问题的解决方法可能是不让mod_perl及其解释器处理请求,而是在使用PerlModule等在VHOST中启动时直接创建自己的Perl线程线程池。这些线程可以完全在Perl中直接管理,可以创建一些队列以绝对路径的形式将工作分派(dispatch)到请求的CGI应用程序等。除了线程池本身之外,还需要一个处理程序,该处理程序将被调用而不是例如ModPerl::Registry充当调度程序:它需要根据一些标准来决定要使用哪个线程,并将请求的路径放入队列中,而线程本身最终可能例如只需创建ModPerl::Registry的新实例即可处理给定的文件。当然这里到处都需要一些胶水。

这种方法当然有一些缺点:听起来工作量相当大,使mod_perl已经实现的某些功能翻了一番,特别是在池维护方面,并使使用的线程和内存数量翻了一番,因为mod_perl解释器和线程只会用于执行调度程序处理程序,另外还有一个线程和解释程序来处理Perl线程中的请求。线程数量根本不是什么大问题,mod_perl中的一个只会休眠并等待Perl线程完成其工作。

@ INC-Hook与源代码更改

我认为更简单的另一种方法是再次使用@INC hooks for Perl's require与扩展ModPerl::Registry的自己的mod_perl处理程序结合使用。关键是处理程序是读取请求的文件的第一个位置,可以在编译文件之前更改其源。每一个

use XY::Z;
XY::Z->new(...);

可以更改为
use SomePrefix::XY::Z;
SomePrefix::XY::Z->new(...);

其中SomePrefix只是被更改为有效Perl package name的所请求文件的父目录的完整路径。 ModPerl::Registry已经执行了类似的操作,而transforming将请求的CGI脚本自动添加到mod_perl处理程序中,因此,它通常可以正常工作,并且ModPerl::Registry已经提供了一些逻辑来生成程序包名称等。更改导致Perl不再自动找到软件包,这仅仅是因为它们在Perl已知的地方不存在新名称,这就是@INC钩子(Hook)适用的地方。

该钩子(Hook)仅由于SomePrefix的名称或SomePrefix前面的标记前缀或其他原因而负责识别更改的软件包,并将其映射到文件系统中的文件以提供所请求文件的句柄,Perl可以加载该文件在“需要”期间。此外,该钩子(Hook)还将提供一个回调,Perl会为读取的文件的每一行调用该回调,并将其用作源代码过滤器,再次更改每个“package”,“use”或“require”语句,以使SomePrefix位于。这将再次导致钩子(Hook)负责为那些包等提供文件句柄。

这里的关键点是在运行时更改源代码一次:在我的目录结构中,n可以使用Perl通常不需要的“XY/Z.pm”,而在Perl中将其替换为“XY/Z.pm”。 %INC,一个让Perl要求的“SomePrefix/XY/Z.pm”,将存储在%INC中,并且对于mod_perl使用的每个Perl解释器来说都是唯一的,因为SomePrefix反射(reflect)了所请求文件的唯一安装目录。 Perl不再有空间认为它已经加载了XY::Z,只是因为它之前已经处理了另一个目录中的请求。

当然,这仅适用于简单的“使用...”。语句,例如“eval(“require $ package”);“会使事情变得更复杂。

欢迎评论... :-)

关于multithreading - 如何通过一些约定使mod_perl解释器具有粘性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27719340/

相关文章:

perl - 如何在 Perl 中使用类属性/变量作为打印文件句柄?

python - grpc server 中 ThreadPoolExecutor 的作用是什么?

perl - 无法获取作为模块中引用传递的哈希值

c++ - 使用 OpenMP 并行化 c++ Monte Carlo Integration 的最佳方法是什么?

apache - 如何使用 .htaccess 拒绝访问当前目录的所有子目录?

apache - 如何使用 apache 在 OVH 互通服务器上禁用 X-Powered-By?

php - 我可以在 Linux (Debian) 中为单个文件夹设置 php.ini 吗?

mysql - 使用 Perl DBD 访问 MySQL 数据库 :ODBC

java - arraylist/atomic double array (Google Guava) 中的 .get() 操作是线程安全的吗?

java - 同时使用多个AnimationDrawables