【发布时间】:2011-03-30 20:31:36
【问题描述】:
SoapClient 请求是否会超时并引发异常。截至目前,我得到 PHP 服务器响应超时,在我的情况下为 60 秒。基本上我想要的是,如果在特定时间内没有来自 Web 服务的任何回复,则会引发异常并且我可以捕获它。 60 秒的警告不是我想要的。
【问题讨论】:
标签: php web-services timeout soap-client
SoapClient 请求是否会超时并引发异常。截至目前,我得到 PHP 服务器响应超时,在我的情况下为 60 秒。基本上我想要的是,如果在特定时间内没有来自 Web 服务的任何回复,则会引发异常并且我可以捕获它。 60 秒的警告不是我想要的。
【问题讨论】:
标签: php web-services timeout soap-client
虽然 Andrei 链接到了一个不错的解决方案,但这个解决方案的代码更少,但却得到了一个很好的解决方案:
* Handling Timeouts with PHP5 SoapClient Extension (by Antonio Ramirez; 02 Feb 2010)
示例代码:
//
// 设置连接超时(示例中为 15 秒)
//
$client = new SoapClient($wsdl, array("connection_timeout" => 15));
如果您需要更细粒度的 HTTP 控制,还有流上下文。参见new SoapClient()Docs 的stream_context选项。在表面之下SoapClient使用 HTTP 和 SSL 传输。
【讨论】:
Unknown SOAP client option Exception
'soap_version' => SOAP_1_1,,但我使用的是Zend_Soap_Client,但它只是扩展了SoapClient
default_socket_timeout
ini_set("default_socket_timeout", 15);
$client = new SoapClient($wsdl, array(......));
connection_timeout 选项为 SOAP 服务的连接。此选项未定义超时 用于响应缓慢的服务。限制等待呼叫的时间 完成 default_socket_timeout 设置可用。
【讨论】:
default_socket_timeout 可能不适用于 HTTPS 连接
default_socket_timeout 适用于响应缓慢的服务。问题是关于处理没有响应的服务。
看看
如果你觉得舒服并且你的环境允许你扩展类。
它基本上扩展了SoapClient 类,将HTTP 传输替换为可以处理超时的curl:
class SoapClientTimeout extends SoapClient
{
private $timeout;
public function __setTimeout($timeout)
{
if (!is_int($timeout) && !is_null($timeout))
{
throw new Exception("Invalid timeout value");
}
$this->timeout = $timeout;
}
public function __doRequest($request, $location, $action, $version, $one_way = FALSE)
{
if (!$this->timeout)
{
// Call via parent because we require no timeout
$response = parent::__doRequest($request, $location, $action, $version, $one_way);
}
else
{
// Call via Curl and use the timeout
$curl = curl_init($location);
curl_setopt($curl, CURLOPT_VERBOSE, FALSE);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_POST, TRUE);
curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
curl_setopt($curl, CURLOPT_HEADER, FALSE);
curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: text/xml"));
curl_setopt($curl, CURLOPT_TIMEOUT, $this->timeout);
$response = curl_exec($curl);
if (curl_errno($curl))
{
throw new Exception(curl_error($curl));
}
curl_close($curl);
}
// Return?
if (!$one_way)
{
return ($response);
}
}
}
【讨论】:
_doRequest() 的签名,没有另行通知。 $request 不再包含原始 XML,而是像 141201299690460051141201717499383133141201717499423132141201717499443131141201717499463131141201717499483135false 这样的字符串。任何人都可以对此有所了解吗?
接受的答案将破坏 SoapClient 必须提供的所有功能。比如设置正确的内容标题、身份验证等。
这将是解决问题的更好方法
class MySoapClient extends \SoapClient
{
private $timeout = 10;
public function __construct($wsdl, array $options)
{
// Defines a timeout in seconds for the connection to the SOAP service.
// This option does not define a timeout for services with slow responses.
// To limit the time to wait for calls to finish the default_socket_timeout setting is available.
if (!isset($options['connection_timeout'])) {
$options['connection_timeout'] = $this->timeout;
}
parent::__construct($wsdl, $options);
}
public function setTimeout($timeout)
{
$this->timeout = $timeout;
}
public function __doRequest($request, $location, $action, $version, $one_way = 0)
{
$original = ini_get('default_socket_timeout');
ini_set('default_socket_timeout', $this->timeout);
$response = parent::__doRequest($request, $location, $action, $version, $one_way);
ini_set('default_socket_timeout', $original);
return $response;
}
}
【讨论】:
default_socket_timeout跨度>
你可以通过 composer 安装它: https://github.com/ideaconnect/idct-soap-client
它扩展了标准 SoapClient 并提供了设置重试次数、连接和读取超时的选项。
【讨论】:
我在使用 SOAPClient 时使用以下逻辑:
public function executeSoapCall($method, $params)
{
try {
$client = $this->tryGetSoapClient();
$timeout = ini_get('default_socket_timeout');
ini_set('default_socket_timeout', 60);//set new timeout value - 60 seconds
$client->__soapCall($method, $params);//execute SOAP call
ini_set('default_socket_timeout', $timeout);//revert timeout back
} catch (\Throwable $e) {
if (isset($timeout)) {
ini_set('default_socket_timeout', $timeout);//revert timeout back
}
}
}
protected function tryGetSoapClient()
{
$timeout = ini_get('default_socket_timeout');//get timeout (need to be reverted back afterwards)
ini_set('default_socket_timeout', 10);//set new timeout value - 10 seconds
try {
$client = new \SoapClient($this->wsdl, $this->options);//get SOAP client
} catch (\Throwable $e) {
ini_set('default_socket_timeout', 10);//revert back in case of exception
throw $e;
}
$this->iniSetTimeout($timeout);//revert back
return $client;
}
这可以帮助我等待长达 10 秒的连接建立和 60 秒的调用执行时间。
【讨论】:
您也可以使用stream_context_create() 并将timeout 选项添加到http 数组中:
$context = stream_context_create(
array(
'http' => array(
"timeout" => 10,
),
)
);
SoapHandler 的初始化应该是:
$soapHandler = new SoapClient($wsdl, [
//more params, if needed..
'stream_context' => $context,
]);
【讨论】: