You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

升级RHEL及PHP 7.2后频繁出现cURL错误28:SSL握手前超时求助

分析与排查:Apache跨主机cURL SSL握手前间歇性超时(Error 28)

针对你遇到的这个间歇性cURL超时问题(Error 28: timed out before SSL handshake),结合你提到的RHEL系统升级、PHP 7.2(IUS源)+OPCache启用的背景,我从几个核心方向拆解成因和排查步骤:

可能的故障成因

  1. OPCache配置冲突或缓存异常:OPCache在加速PHP代码的过程中,可能误缓存了curl扩展的SSL上下文相关逻辑,或者缓存的连接资源没有正确释放,导致间歇性的连接初始化失败。尤其是升级PHP后,旧的缓存规则可能和新的PHP版本不兼容。
  2. 系统依赖库版本不兼容yum update可能更新了OpenSSL、libcurl这类底层库,而IUS源提供的PHP 7.2的curl扩展可能和系统更新后的libcurl版本存在适配问题,导致SSL握手前的连接阶段出现间歇性故障。
  3. 网络层面的连接跟踪或资源限制:比如系统的nf_conntrack连接跟踪表满了,导致新的SSL连接请求被内核丢弃;或者防火墙/路由器的连接超时设置过短,在网络轻微波动时就触发超时。
  4. Apache/PHP-FPM的资源耗尽:如果Apache的MPM模式配置不合理,或者PHP-FPM的进程池参数设置过小,并发请求时会出现资源不足,无法建立新的SSL连接,表现为间歇性超时。
  5. PHP curl扩展的超时参数设置过严:默认的连接超时、SSL握手超时设置太短,在网络不稳定的时候就容易触发Error 28。

分步排查指南

一、先排除网络与系统底层问题

  • 检查连接跟踪表状态
    执行cat /proc/net/nf_conntrack | wc -l统计当前连接数,再用sysctl net.netfilter.nf_conntrack_max查看系统允许的最大连接数。如果当前数接近最大值,说明连接跟踪表满了,临时调大试试:
    sysctl -w net.netfilter.nf_conntrack_max=100000
    
    生效后观察是否还出现超时,确认后把这个值写入/etc/sysctl.conf永久生效。
  • 抓包定位网络异常
    当问题出现时,用tcpdump抓包分析:
    tcpdump -i any host <目标主机IP> and port 443 -w curl_timeout.pcap
    
    用Wireshark打开捕获的文件,重点看:是否有SYN包发出但无SYN-ACK响应?或者Client Hello发出后没有Server Hello?这能直接判断是链路问题还是目标服务器的问题。
  • 验证DNS解析稳定性
    多次执行dig <目标域名>,看解析IP是否一致、响应时间是否稳定。如果解析有延迟或波动,可以临时在/etc/hosts里添加静态域名解析,再测试问题是否消失。
  • 临时关闭SELinux和防火墙测试
    执行setenforce 0临时关闭SELinux,同时暂停firewalld(systemctl stop firewalld),观察是否还会出现超时。如果问题消失,再逐步排查SELinux策略或防火墙规则的限制。

二、排查PHP与OPCache相关问题

  • 临时禁用OPCache验证
    修改/etc/php.d/opcache.ini(或对应路径的配置文件),设置opcache.enable=0,然后重启Apache或PHP-FPM。如果禁用后问题不再出现,那就是OPCache的问题。
    针对OPCache的修复方向:
    • 检查opcache.memory_consumption是否足够(建议至少128M),opcache.max_accelerated_files是否覆盖了所有业务PHP文件;
    • 开启opcache.validate_timestamps=1,让OPCache定期校验文件更新,避免缓存过期代码;
    • 执行opcache_reset()手动清理缓存,或者重启服务清空缓存。
  • 检查curl扩展与系统libcurl兼容性
    执行php -i | grep "curl"查看PHP的curl扩展版本,再执行curl --version查看系统的libcurl版本。如果两者版本差异较大(比如PHP用7.2的curl扩展,系统libcurl是较新的7.6+),可能存在适配问题。可以尝试重新安装IUS源的PHP curl扩展包:
    yum reinstall php72u-curl
    
  • 调整curl代码中的超时参数
    在你的PHP代码里显式设置更长的超时时间,覆盖默认值:
    $ch = curl_init('<目标URL>');
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); // 连接超时10秒
    curl_setopt($ch, CURLOPT_TIMEOUT, 30); // 总请求超时30秒
    curl_setopt($ch, CURLOPT_SSL_CONNECT_TIMEOUT, 5); // SSL握手超时5秒
    // 其他必要配置...
    $response = curl_exec($ch);
    
    观察是否还会触发超时。

三、排查Apache与PHP-FPM的资源配置

  • 检查Apache MPM配置
    打开/etc/httpd/conf/httpd.conf(或/etc/httpd/conf.modules.d/00-mpm.conf),根据你的MPM模式调整参数:
    • 若为prefork:确保MaxClients(或MaxRequestWorkers)、ServerLimit足够处理并发;
    • 若为worker/event:调整ThreadsPerChildMaxRequestWorkers
      apachectl status查看当前连接数和进程状态,确认是否有资源耗尽的情况。
  • 检查PHP-FPM进程池配置
    打开/etc/php-fpm.d/www.conf,检查pm.max_childrenpm.start_servers等参数,确保进程数足够。执行ps aux | grep php-fpm看当前运行的进程数,如果接近pm.max_children的限制,就调大这个值。同时检查request_terminate_timeout,避免进程长时间占用资源。
  • 查看错误日志
    检查/var/log/httpd/error_log/var/log/php-fpm/error.log(路径可能因系统而异),看是否有资源不足、连接被拒绝等相关日志,这些日志能直接指向问题根源。

四、目标服务器端排查(若有权限)

如果能访问目标服务器,检查以下几点:

  • 目标服务器的Web服务日志(Apache/Nginx),看是否有来自你的服务器的连接被拒绝或超时记录;
  • 目标服务器的CPU、内存、带宽使用情况,是否在超时时刻出现资源耗尽;
  • 目标服务器的SSL配置,比如是否开启了SSL会话复用,是否有针对特定客户端的访问限制。

内容的提问来源于stack exchange,提问作者DrZ

火山引擎 最新活动