SOAP::Lite - 使用 1.1 和 1.2 版线程的客户端 mod_perl
SOAP::Lite - clients using version 1.1 and 1.2 threaded in mod_perl
我在 Apache hhtpd 的 mod_perl 下有几个 SOAP::Lite 客户端 运行ning。
其中一些使用 1.1 soap-servers,一些使用 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()
被调用时 $SOAP::Constants
设置为适合版本 1.2 - 导致多个命名空间错误,特别是:
xmlns:soapenc="http://www.w3.org/2003/05/soap-encoding"
1.1 的哪个错误 - 谁更喜欢:
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
如果我能以某种方式使 $SOAP::Constants
本地化到服务器线程或类似的东西,我想一切都会好起来的。但任何解决方案将不胜感激。
运行 Apache 使用 prefork 模型而不是线程模型(mpm_prefork_module
而不是 mpm_event_module
或 mpm_worker_module
),这样每个 Apache 子节点都会有自己的Perl 解释器,因此它有自己的一组常量。
否则请查看有关 PerlOptions
指令的 modperl 文档,特别是 clone
and/or parent
值。但是停止使用线程对我来说似乎更简单,线程和 Perl 从来就不是朋友。
我在 Apache hhtpd 的 mod_perl 下有几个 SOAP::Lite 客户端 运行ning。 其中一些使用 1.1 soap-servers,一些使用 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()
被调用时 $SOAP::Constants
设置为适合版本 1.2 - 导致多个命名空间错误,特别是:
xmlns:soapenc="http://www.w3.org/2003/05/soap-encoding"
1.1 的哪个错误 - 谁更喜欢:
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
如果我能以某种方式使 $SOAP::Constants
本地化到服务器线程或类似的东西,我想一切都会好起来的。但任何解决方案将不胜感激。
运行 Apache 使用 prefork 模型而不是线程模型(mpm_prefork_module
而不是 mpm_event_module
或 mpm_worker_module
),这样每个 Apache 子节点都会有自己的Perl 解释器,因此它有自己的一组常量。
否则请查看有关 PerlOptions
指令的 modperl 文档,特别是 clone
and/or parent
值。但是停止使用线程对我来说似乎更简单,线程和 Perl 从来就不是朋友。