有时,即使传递给该方法的参数与通常用一秒钟的时间相同,缺省类方法有时也会失败,这是很奇怪的。
第script_line_number行的script_path中的最大执行时间超过30秒
在该行中:
$result = $DOMDocument -> schemaValidate($schemaPath);
$ DOMDocument始终相同。并且它仅引用ID属性为相同XML的部分。除了Algorith和xmlns之外,它没有任何类似URL的属性,它们本质上不会从任何地方调用anyresource,我们正在谈论PHP的DOMDocument类和XML starndards。
$schemaPath
始终相同,并且指向服务器本地XSD文件,该文件在验证尝试之前和之后始终存在,无论成功与否,该文件始终存在。该模式仅指向位于同一文件夹中的其他本地xsd文件,即<xs:include schemaLocation="schema2.xsd"/>
我能想到的唯一可能的答案是,通过该方法可以找到XSD文件,但由于光盘繁忙,由于某种原因它无法读取。
是什么原因导致方法执行时间太长?
除了增加PHP的最大执行时间限制外,还应采取什么措施防止错误发生?
XML和XSD文件非常小,实际上,完全相同的XML和XSD通常花费不到0.1秒的时间来进行验证,但是执行时间却很少(1000次中的1分)超过了30秒。
编辑
我隔离了问题,因此发布了样本。
Schema.xsd:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema targetNamespace="http://www.foo.bar/Car" xmlns:SiiDte="http://www.foo.bar/Car" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:include schemaLocation="schema2.xsd"/>
<xs:import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="xmldsignature_v10.xsd"/><!-- just the standar signature schema -->
<xs:element name="ROOT" type="SiiDte:ROOTDefType"/>
<xs:complexType name="ROOTDefType">
<xs:sequence>
<xs:element name="Element"></xs:element>
<xs:element ref="ds:Signature">
<xs:annotation>
<xs:documentation>Firma Digital sobre Documento</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
<xs:attribute name="version" type="xs:decimal" use="required" fixed="1.0"/>
</xs:complexType>
</xs:schema>
Schema2.xsd:
<xs:schema targetNamespace="http://www.foo.bar/Car" xmlns:ns1="http://www.foo.bar/Car" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:simpleType name="MOOType">
<xs:restriction base="xs:positiveInteger">
<xs:enumeration value="1"/>
<xs:enumeration value="2"/>
<xs:enumeration value="3"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
代码:
// ... a bunch of ther code...
$XML =
'<?xml version="1.0"?>
<ROOT xmlns="http://www.foo.bar/Car" version="1.0">
<Element ID="A1">hello</Element>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#A1">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>base64string</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>base64string</SignatureValue>
<KeyInfo>
<KeyValue>
<RSAKeyValue>
<Modulus>base64string</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
</KeyValue>
<X509Data>
<X509Certificate>base64string</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</ROOT>'
;
$DD = new DOMDocument();
$DD -> loadXML($XML);
$i = 0;
while ($i < 100) {
// ... a bunch of other code...
libxml_use_internal_errors(true);
$old_libxml_disable_entity_loader = libxml_disable_entity_loader(false); $result = $DD -> schemaValidate(__DIR__ . '/schema.xsd');
libxml_disable_entity_loader($old_libxml_disable_entity_loader); // Se desactiva nuevamente carga de entidades para descartar entidades maliciosas
$i++;
echo str_pad($i, 5) . ($result ? 'true' : 'false') . '<br>';
// ... a bunch of other code...
}
问题在于整个脚本已达到30秒标记,而不是仅执行DOMDocument :: schemaValidate()。
执行时间对应于完整脚本的执行时间,包括所有脚本的执行和迭代(如果有的话)。
考虑到执行时间不包括脚本外花费的任何时间,例如流操作,数据库查询等等。因此,举例来说,该脚本看起来好像只占用了1分钟,而实际上只占用了15或30。请参见http://php.net/manual/en/function.set-time-limit.php,其中指出:
注意:set_time_limit()函数和配置指令max_execution_time仅影响脚本本身的执行时间。确定脚本已运行的最长时间时,不包括执行脚本之外发生的活动上的任何时间,例如使用system()进行系统调用,流操作,数据库查询等。在测量的时间是真实的Windows上不是这样。
不是:: schemaValidate()需要30秒才能执行,而是完整的脚本。那么,为什么脚本一旦达到30秒,错误便落在schemaValidate()内部?因为altought :: schemaValidate()是一种执行起来相对较快的方法,因此它必须是迭代中最复杂的代码,因此,最大的机会是在执行N次重复后,schemaValidate执行时错误降落了(在实际情况下,N必须很多)。
因此,答案是:: schemaValidate()占用了大部分执行时间,因此,始终在:: schemaValidate()执行时,错误总是在虚拟状态下发生。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句