1

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

如何尽早发送 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 提交后关闭套接字并继续处理,这样我就不会在发送服务器上遇到这些超时问题?

4

2 回答 2

1

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
于 2010-06-28T15:36:19.573 回答
1

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

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

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

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


其他吐槽:

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