3

我有几个 SOAP::Lite 客户端在 Apache hhtpd 的 mod_perl 下运行。他们中的一些人使用 1.1 的肥皂服务器,而他们中的一些人使用 1.2 的服务器。所以我有如下代码:

# In client 1:
my $soap1 = SOAP::Lite->soapversion("1.1");
$result1 = $soap1->method1();

# In client 2:
my $soap2 = SOAP::Lite->soapversion("1.2");
$result2 = $soap2->method2();

这适用于独立客户端,但是当我在 mod_perl 下运行代码时,我似乎被该soapversion 方法有副作用所刺痛:

# From SOAP::Lite.pm 
sub soapversion {
    my $self = shift;
    my $version = shift or return $SOAP::Constants::SOAP_VERSION;

    ($version) = grep {
        $SOAP::Constants::SOAP_VERSIONS{$_}->{NS_ENV} eq $version
        } keys %SOAP::Constants::SOAP_VERSIONS
            unless exists $SOAP::Constants::SOAP_VERSIONS{$version};

    die qq!$SOAP::Constants::WRONG_VERSION Supported versions:\n@{[
        join "\n", map {"  $_ ($SOAP::Constants::SOAP_VERSIONS{$_}->{NS_ENV})"} keys %SOAP::Constants::SOAP_VERSIONS
        ]}\n!
        unless defined($version) && defined(my $def = $SOAP::Constants::SOAP_VERSIONS{$version});

    foreach (keys %$def) {
        eval "\$SOAP::Constants::$_ = '$SOAP::Constants::SOAP_VERSIONS{$version}->{$_}'";
    }

    $SOAP::Constants::SOAP_VERSION = $version;

    return $self;
}

这就是我认为会发生的事情:

基本上,该soapversion调用重新定义了$SOAP::Constants. 而且由于这是 mod_perl,它$SOAP::Constants是全局的,并且在每个服务器线程之间共享(我相信。如果我错了,请纠正我)。这导致了竞争条件:大多数时候,代码行或多或少地按照上面看到的顺序执行。但是偶尔(实际上大约 2% 的调用)执行顺序是:

Thread1: my $soap1 = SOAP::Lite->soapversion("1.1");
Thread2: my $soap2 = SOAP::Lite->soapversion("1.2");
Thread1: $result1 = $soap1->method1();
Thread2: $result2 = $soap2->method2();

因此,$soap1->method1()使用 set 作为适合版本 1.2 调用的$SOAP::Constants方法 - 导致多个命名空间出错,特别是:

xmlns:soapenc="http://www.w3.org/2003/05/soap-encoding" 

这对 1.1 来说是错误的 - 谁更喜欢:

xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"                                                 

如果我能以某种方式$SOAP::Constants本地化到服务器线程或类似的东西,我想一切都会好起来的。但任何解决方案将不胜感激。

4

1 回答 1

1

使用 prefork 模型而不是线程模型(mpm_prefork_module而不是mpm_event_moduleor mpm_worker_module)运行 Apache,这样每个 Apache 子节点都将拥有自己的 Perl 解释器,从而拥有自己的一组常量。

否则,请查看有关PerlOptions指令的 modperl 文档,特别是clone和/或parent值。但是停止使用线程对我来说似乎更简单,线程和 Perl 从来都不是朋友。

于 2017-01-30T01:47:06.410 回答