【问题标题】:use methods in different modules in mod_perl handler在 mod_perl 处理程序的不同模块中使用方法
【发布时间】:2013-08-03 22:36:06
【问题描述】:

我想在不同的 perl 模块之间共享一个变量。所以我创建了一个名为 MyCache.pm 的 perl 模块,它保存了变量(在我的例子中是一个哈希变量):

package PerlModules::MyCache;
my %cache = ();
sub set {
  my ($key, $value) = @_;
  $cache{$key} = $value;
}
sub get {
  my ($key) = @_;
  return $cache{$key};
}

现在我有两个处理程序。一个处理程序将调用 set 方法,另一个将调用 get 方法来访问信息。

package PerlModules::MyCacheSetter;
use Apache2::RequestRec();
use Apache2::RequestIO();
use Apache2::Const -compile => qw(OK);
use PerlModules::MyCache;
sub handler {
  my $r = shift;
  PerlModules::MyCache::set('test1', "true");
  PerlModules::MyCache::set('test2', "false");
  PerlModules::MyCache::set('test3', "true");
  return Apache2::Const::OK;
}

这里是 getter 处理程序:

package PerlModules::MyCacheGetter;
use Apache2::RequestRec();
use Apache2::RequestIO();
use Apache2::Const -compile => qw(OK);
use PerlModules::MyCache;
sub handler {
  my $r = shift;
  $r->print(PerlModules::MyCache::get('test1'));
  $r->print(PerlModules::MyCache::get('test2'));
  $r->print(PerlModules::MyCache::get('test3'));
  return Apache2::Const::OK;
}

现在我已经配置了 apache(通过 http.conf)来访问这些 perl 模块。我运行 setter 处理程序,然后运行 ​​getter,但没有输出。

在 error.log 中现在有一些条目:

Use of uninitialized value in subroutine entry at ../MyCacheGetter.pm line 14.
Use of uninitialized value in subroutine entry at ../MyCacheGetter.pm line 15.
Use of uninitialized value in subroutine entry at ../MyCacheGetter.pm line 16.

这一行是get方法的三个调用。那么我做错了什么?如何解决问题并在不同的处理程序之间共享我的缓存变量?

【问题讨论】:

  • 您是否在同一个请求中运行 setter 处理程序和 getter 处理程序?如果您展示如何调用处理程序,也许会有所帮助。
  • 嗨,我正在使用以下 httpd.conf 配置来访问处理程序。在此之后,我通过 webbrowser 调用处理程序(localhost/mcsetter): PerlModule PerlModules::MyCacheGetter SetHandler modperl PerlResponseHandler PerlModules::MyCacheGetter 和 setter 相同。
  • 您是否在发出两个单独的 HTTP 请求(1 个用于设置,另一个用于获取)?如果是这样,您可能会得到两个不同的 Apache 子进程的服务。你做了什么来将你的缓存状态传达给其他子进程?
  • 是的。我需要发出两个单独的 HTTP 请求。我已将 apache2.conf 文件中 apache 的配置更改为:StartServers 1、MinSpareServers 1、MaxSpareServers 1、MaxClients 5。如果我将 MaxClients 更改为 1 它将起作用,但有时我会收到一个 apache 错误没有足够的客户。
  • @ManuelHinz 当您发出多个请求时,您很可能会遇到不同的 Apache 子节点。这就是为什么当您限制数量时,您会得到相同的子进程并且它“有效”。但是,您真的不想限制 Apache 子节点的数量,您需要修复应用程序的架构。 (续...)

标签: perl apache handler mod-perl mod-perl2


【解决方案1】:

您的缓存只会在给定的 Apache 子进程的生命周期内存在。如果您希望其他进程看到它,则需要将其存储在他们都可以访问的地方。

这是未经测试的,但您可以大致了解:(现已测试)。 编辑:好的,您似乎可以在Storable 上遇到一些问题,具体取决于您正在运行的 perl 版本和Storable 版本。在我的示例中,我已将 Storable 替换为 Data::Serialize。我还在get/set 方法中添加了一行,以便可以使用->:: 语法。

package PerlModules::MyCache;

use IPC::ShareLite qw/:lock/;
use Data::Serializer;
use 5.10.0;

my $key = 1234; # Your shared memory key (you set this!)

my $ipc = IPC::ShareLite->new(
    -key     => $key,
    -create  => 'yes',
    -destroy => 'no'
);

my $ser = Data::Serializer->new(
    serializer => 'Data::Dumper'
);

sub set {
    shift @_ if $_[0] eq __PACKAGE__;
    my ($key, $value) = @_;
    $ipc->lock(LOCK_EX);
    my $frozen; eval { $frozen = $ipc->fetch; };
    my $cache = defined($frozen) ? $ser->thaw($frozen) : {};
    $cache->{$key} = $value;
    $ipc->store($ser->freeze($cache));
    $ipc->unlock;
    return $value;
}

sub get {
    shift @_ if $_[0] eq __PACKAGE__;
    my ($key) = @_;
    my $frozen; eval { $frozen = $ipc->fetch; };
    my $cache = defined($frozen) ? $ser->thaw($frozen) : {};
    return $cache->{$key};
}

sub clear {
    shift @_ if $_[0] eq __PACKAGE__;
    $ipc->store($ser->freeze({}));
    return {};
}

1;

您可能希望在测试前运行一次PerlModules::MyCache->clear,以确保缓存存储结构正确。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-04
    • 1970-01-01
    • 2011-03-09
    • 2016-05-11
    • 1970-01-01
    • 1970-01-01
    • 2013-01-24
    相关资源
    最近更新 更多