PHP 提前发送 SOAP 响应?
嗯,这是我一直在处理的一个老问题,但仍然没有解决方案,所以尝试一种新方法。
如何尽早发送 SOAP 响应(在脚本执行结束之前)?
这些问题是由于未在 30 秒之前发送 ACK 文件而导致的,因为完成该过程所需的时间比分配的时间更长。
lush() 不起作用,出现此错误:
org.xml.sax.SAXParseException:XML 文档结构必须在同一实体内开始和结束。
没有flush()我得到这个
org.xml.sax.SAXParseException:文件过早结束。
脚本进程可以接管 180 秒才能完成,等待响应的服务器只等待大约 30 秒就超时(这会导致上述错误)。
关于如何解决这个问题有什么想法吗?
以下是一些代码: 这是我接受和发送即将到来的 SOAP 请求的 ACK 文件的方式
$data = 'php://input';
$content = file_get_contents($data);
if($content) {
respond('true');
} else {
respond('false');
}
PHP的响应函数
function respond($tf) {
$ACK = <<<ACK
<?xml version = "1.0" encoding = "utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<notifications xmlns="http://soap.sforce.com/2005/09/outbound">
<Ack>$tf</Ack>
</notifications>
</soapenv:Body>
</soapenv:Envelope>
ACK;
print trim($ACK);
}
使用单线程处理方法,并且在线程完成其处理之前不会发回 ACK 文件。有没有什么方法可以在提交 ACK 后关闭套接字并继续处理,这样我就不会在发送服务器上遇到这些超时问题?
Well this is an old issue I've been dealing with and still no solution, so trying a new approach.
How can I send th SOAP response early (Before script execution ends)?
These issues are cause when the ACK file is not sent before 30 seconds as the process takes longer to complete then the allotted time.
flush() not working, get this error:
org.xml.sax.SAXParseException: XML document structures must start and end within the same entity.
without the flush() I get this
org.xml.sax.SAXParseException: Premature end of file.
The script process can takeover 180 seconds to complete and the server waiting for the response only wait for about 30 seconds before timing out (Which cause the above error).
any thoughts as to how I can fix this?
Here is some of the code: This is how I accept and send the ACK file for the imcoming SOAP request
$data = 'php://input';
$content = file_get_contents($data);
if($content) {
respond('true');
} else {
respond('false');
}
The respond function
function respond($tf) {
$ACK = <<<ACK
<?xml version = "1.0" encoding = "utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<notifications xmlns="http://soap.sforce.com/2005/09/outbound">
<Ack>$tf</Ack>
</notifications>
</soapenv:Body>
</soapenv:Envelope>
ACK;
print trim($ACK);
}
PHP uses a single thread processing approach and will not send back the ACK file until the thread has completed it's processing. Is there some way to close the socket after the ACK submission and continue the processing so I don't get these timeout issues on the sending server?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
据我所知,我们无法对 30 秒的限制做任何事情,并且在脚本完成之前输出不会被刷新。你能尝试将你的处理逻辑分成两部分吗?
“要完成的工作”可能是一个新生成的进程(查看 pcntl_fork() 函数,但它们对我来说看起来不太有希望)或某种将数据存储在文件或数据库中并使用另一个脚本定期处理它的方法,例如计划每 5 分钟运行一次?
如果 60 秒能以某种方式拯救您,您可以将出站消息重写为来自 Apex 的标注。基本上,您可以编写自己的 SOAP 信封并将其发送到任何 http 地址。你可以把它放在触发器中。不过,请参阅此处了解此方法的局限性。
其他咆哮:
As far as I know we can't do anything about the 30 second limit and the output won't be flushed before the script finishes. Can you try splitting your processing logic into 2 pieces?
The "job to be done" could be a newly spawned process (check out the comments for the pcntl_fork() function but they don't look too promising to me) or some way to store the data in file or database and periodically process it with another script, for example scheduled to run every 5 minutes?
If 60 seconds would somehow save you, you could rewrite your outbound message into a callout from Apex. Basically you then write your own SOAP envelope and send it to any http address. You could put it in a trigger. See here for limitations of this approach though.
Other ranting:
a) (可选)您可以使用 set_time_limit() 来增加执行时间的时间限制。
b) 您必须增加 wsdl 客户端对象的时间,例如:
大多数 wsdl 类允许定义超时。
c) 而不是,您无法使用 SOAP 尽早响应,至少不能使用一次调用。考虑到 SOAP 返回 XML,因此部分 XML 通常是无效的(它缺少结束标记)。
d) 或者,您可以使用 SOAP 以外的其他方法,例如读取 url:
其中 url.php 返回列(或不使用 xml 的某种值:
a) (optional) you can use set_time_limit() for increase the time limit of the execution time.
b) You must increase the time to the wsdl client object, for example :
Most wsdl class allow to define the timeout.
c) and not, you can't response early using SOAP, not at least using one call. Take in consideration that SOAP return a XML, so a partial XML usually is invalid (it miss the closing tag).
d) Alternate, you can use other method than SOAP, for example reading a url:
where url.php return the columns (or some kind of value without using xml :