【问题标题】:PHP send SOAP response early?PHP 提前发送 SOAP 响应?
【发布时间】:2010-06-28 15:26:44
【问题描述】:

这是一个我一直在处理的老问题,但仍然没有解决方案,所以尝试一种新方法。

如何提前(在脚本执行结束之前)发送 SOAP 响应?

这些问题是在 30 秒之前未发送 ACK 文件时引起的,因为该过程需要比分配的时间更长的时间才能完成。

flush() 不工作,得到这个错误:

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');
}

响应函数

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 使用单线程处理方法,在线程完成处理之前不会发回 ACK 文件。有没有办法在 ACK 提交后关闭套接字并继续处理,这样我就不会在发送服务器上遇到这些超时问题?

【问题讨论】:

    标签: php xml soap salesforce flush


    【解决方案1】:

    据我所知,我们无法对 30 秒的限制做任何事情,并且在脚本完成之前不会刷新输出。你能试着把你的处理逻辑分成两部分吗?

    1. “侦听器”脚本,用于接受消息、记录要完成的工作并立即发送 ACK,然后退出。
    2. 您方的实际处理可能需要更长时间。

    “要完成的工作”可能是一个新产生的进程(查看 pcntl_fork() 函数的 cmets,但它们看起来对我来说不太有希望)或将数据存储在文件或数据库中的某种方式,以及使用另一个脚本定期处理它,例如计划每 5 分钟运行一次?

    如果 60 秒能以某种方式节省您的时间,您可以将出站消息重写为 Apex 的标注。基本上,然后您编写自己的 SOAP 信封并将其发送到任何 http 地址。你可以把它放在触发器里。不过,请参阅 here 了解此方法的限制。


    其他吐槽:

    1. 我认为您的 ACK 对销售人员来说并不真正“重要”。出站消息只是通知。您是否在应用程序中的其他地方依赖 Ack = true/false?如果不是 - 盲目发送 ack=true 并安排工作的侦听器可能真的是要走的路;)
    2. 从另一个问题我了解到,您基本上只需将更新存储在您身边的数据库中。您意识到您不应该将 OM 用于审计目的,对吗? (Link,搜索“审计”)。
    3. 让 PHP 成为主动方不是更简单吗?让它在 Salesforce 中查询 [SELECT Id, Name FROM Account WHERE LastModifiedDate > :lastTimeYouQueried]?这样你就可以花所有的时间来处理结果:)

    【讨论】:

      【解决方案2】:

      a)(可选)您可以使用 set_time_limit() 来增加执行时间的时间限制。

      b) 你必须增加 wsdl 客户端对象的时间,例如:

      $clientwsdl->setOpt('timeout', 300); // if you are using PEAR:SOAP.
      

      大多数 wsdl 类允许定义超时。

      c) 而不是,您不能使用 SOAP 及早响应,至少不能使用一次调用。考虑到 SOAP 返回一个 XML,所以部分 XML 通常是无效的(它错过了结束标记)。

      d) 或者,您可以使用 SOAP 以外的其他方法,例如读取 url:

      $fp=fopen("http://www.mysite.com/url.php","r");
      

      url.php 在哪里返回列(或不使用 xml 的某种值:

      30|50|70|80|20 
      30|50|70|80|20
      30|50|70|80|20
      

      【讨论】:

      • 感谢您的输入,尝试设置 setOpt() 时遇到问题,至于其他 fopen 方法,我无法从 XML 更改
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-10
      • 1970-01-01
      相关资源
      最近更新 更多