PHP SoapClient:SoapFault 异常无法连接到主机

PHP SoapClient: SoapFault exception Could not connect to host

我使用此代码发出 soap 请求

$client = new SoapClient('http://example.com/soap/wsdl');

try {
    $result = $client->myMethod();
} catch (Exception $e) {
    echo $e->getMessage();
}

有时(十分之一)会引发异常:

SoapFault exception: [HTTP] Could not connect to host

我的尝试

1) 我寻找解决方案,I read 这个问题可能是由 wsdl 缓存引起的,我在 php.ini:

中禁用了它
soap.wsdl_cache_enabled = 0
soap.wsdl_cache_ttl = 0

引发更少的异常

2) 我试图将 windows 的主机(它们在 windows 上)添加到 windows/system32/drivers/etc/hosts:

中的 dns 分辨率
160.XX.XXX.XX example.com

引发更少的异常

3) 我也尝试禁用 "Windows Firewall",

引发更少的异常

4) 我也试过在php.ini

中增加default_socket_timeout
default_socket_timeout = 90

没有任何变化

问题

服务器 soap 似乎没有 problems.It 使用其他站点也没有问题。还有什么我可以做的吗?

我的设置

PHP 5.6

Apache 2.4

Windows Server 2012

更新

经过多次测试,我认为问题出在网络上,soap服务器在反向代理后面,问题出现在代理上。

您需要进一步改进调试工作:

ad 1) WSDL 变化很大吗?如果没有,打开 WSDL 缓存。您无需连接到服务器即可获取 WSDL 文件。

你提到的输出真的是在echo $e->getMessage();中创建的吗?您可以在 catch() 块中添加一些调试代码,例如:

  • 检查您是否可以通过其他方式连接到服务器(例如 file_get_contents($soap_url)
  • 如果不是,请检查您收到的错误类型
    • 打印时间并检查 SOAP 服务器上的错误日志
    • a 403 Forbidden 或服务器上出现问题的类似错误点
    • a Could not connect 错误指向网络问题(不完全是,但可能性更高)
  • 你可以试着把它放在一个循环中(类似于 for ($i = 0; $i <= 5; $i++) { /* ... */ sleep(1); continue; } 的东西)看看第二次尝试是否能成功

总而言之,"sometimes errors"很难调试,所以你要么尝试使其可重现(这将指向问题),要么你需要尽可能多地记录和输出数据以便您可以看到问题发生时的位置。

您是否尝试过在浏览器中或通过 wget 或类似工具打开 URL?然后尝试刷新无数次,看看是否有任何错误发生。我的猜测是这是一个网络问题,但事实上,不稳定的网络使得调试变得非常困难...

请检查服务器上的keep alive 是否处于活动状态并尝试更改其参数。 WSDL 获取和请求发送之间的连接可能有问题。

如果 WSDL 文件永远不会更改,您可以尝试禁用并检查是否再次出现此错误。只需将 wsdl 设置为 null 并设置位置和 uri。

我只是想在此基础上再添加一个可能有用的提示。除了已经写在此处的其他有用答案之外,您还应该检查一下。

如果您从 php 5.5 或更早版本升级到 PHP 5.6 或 PHP7+,您可能会看到此错误。 PHP 较新版本中 soap 的默认设置是验证远程对等点(应该如此)。如果您从 HTTPS 中提取 WSDL 或具有 HTTPS 端点,那么它将检查 CA。如果失败,您将收到此特定错误。

有两种方法可以解决这个问题。

1) 最安全的选择是验证对等方。在 ubuntu 系统上,您将以 root 身份将证书复制到 /usr/local/share/ca-certificates/ 和 运行 update-ca-certificates

2) 或者您可以在此处禁用验证,这是一个如何执行此操作的示例。 - 这通常不是首选选项,但如果问题很紧急,它可以提供快速修复。不过请不要马虎对待您的安全。

$soapClient = new SoapClient($wsdl_url, array(
    //'trace' => 1,
    'stream_context' => stream_context_create(array(
        'ssl' => array(
            'verify_peer' => false,
            'verify_peer_name' => false, 
            'allow_self_signed' => true //can fiddle with this one.
        )
    ))
 ));

我发现 PHP 文档在涉及 SOAP 时有点零散。尤其是 SOAP WSSE。

使用它来清除脚本中的 soap 缓存:

ini_set('soap.wsdl_cache_enabled',0);
ini_set('soap.wsdl_cache_ttl',0);