如何在生产 Web 服务器上的 Apache/mod_perl 下测试 Web Perl 模块?
我们有一个设置,其中大多数代码在升级到完整生产之前,都以 BETA 模式部署 - 这意味着它在完整生产环境中运行(使用生产数据库 - 通常是生产数据;以及生产 Web 服务器)。我们称该阶段为BETA 测试。
主要要求之一是,BETA 代码升级到生产环境必须是从 beta 目录到生产目录的简单“cp”命令 - 无需更改代码/文件名。
对于非 Web Perl 代码,实现无缝 BETA 测试是完全可行的(在此处查看详细信息):
- Perl 程序位于生产根目录下的标准位置 (
/usr/code/scripts
),生产 perl 模块位于同一根目录下(/usr/code/lib/perl
) - BETA 代码具有 100% 相同的代码路径,除了在 beta 根目录下 (
/usr/code/beta/
) - 一个特殊的模块操作任何脚本的
@INC
,取决于该脚本是从/usr/code/scripts
还是/usr/code/test/scripts
调用的,包含 beta 脚本的 beta 库。
这个设置工作得很好,直到我们需要对我们的 Web Perl 代码进行 Beta 测试(设置是 EmbPerl 和 Apache/mod_perl)。
挂起如下:如果生产 Perl 模块和 BETA Perl 模块具有相同的名称(例如 /usr/code/lib/perl/MyLib1.pm
和 /usr/code/beta/lib/perl/MyLib1.pm
),那么 mod_perl 将只能将其中一个模块加载到内存中 - 并且我们无法知道特定的模块由于并发问题,网页会影响当前加载的模块版本。
撇开明显的非编程解决方案(获取一个该死的BETA Web服务器)不谈,因为政治/组织原因这是不可行的,我们有什么办法可以在Perl或mod_perl中以某种方式解决这个问题吗?
我尝试了各种方法来卸载 %INC
列出的 Perl 模块,但问题仍然是另一个用户可能会在正确(或更确切地说错误)的时刻加载 beta 页面并拥有 beta 模块已加载,它将用于我的生产页面。
We have a setup where most code, before being promoted to full production, is deployed in BETA mode - meaning, it runs in full production environment (using production database - usually production data; and production web server). We call that stage BETA testing.
One of the main requirements is that BETA code promotion to production must be a simple "cp" command from beta to production directory - no code/filename changes.
For non-web Perl code, achieving seamless BETA test is quite doable (see details here):
- Perl programs live in a standard location under production root (
/usr/code/scripts
) with production perl modules living under the same root (/usr/code/lib/perl
) - The BETA code has 100% same code paths except under beta root (
/usr/code/beta/
) - A special module manipulates
@INC
of any script based on whether the script was called from/usr/code/scripts
or/usr/code/test/scripts
, to include beta libraries for beta scripts.
This setup works fine up till we need to beta test our web Perl code (the setup is EmbPerl and Apache/mod_perl).
The hang-up is as follows: if both a production Perl module and BETA Perl module have the same name (e.g. /usr/code/lib/perl/MyLib1.pm
and /usr/code/beta/lib/perl/MyLib1.pm
), then mod_perl will only be able to load ONE of these modules into memory - and there's no way we are aware of for a particular web page to affect which version of the module is currently loaded due to concurrency issues.
Leaving aside the obvious non-programming solution (get a bloody BETA web server) which for political/organizational reasons is not feasible, is there any way we can somehow hack around this problem in either Perl or mod_perl?
I played around with various approaches to unloading Perl modules that %INC
has listed, but the problem remains that another user might load a beta page at just the right (or rather wrong) moment and have the beta module loaded which will be used for my production page.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
使用 mod_perl 2.0,您可以使用 PerlOptions +Parent 来为每个虚拟主机创建一个单独的 Perl 解释器池。当然,这会花费你额外的内存,但它会起作用。
Using mod_perl 2.0 you can use PerlOptions +Parent to create a separate Perl interpreter pool for each vhost. It will cost you extra memory, of course, but it will work.