#1161·workerman

Swoole6.2.1 事件循环下 HTTPS 请求超时:stream_socket_enable_crypto() 返回 false

Author: 21307369Created Jul 8, 2026Updated Aug 23, 2026

问题描述

在 Swoole 事件循环下,使用 Workerman\Http\Client 发起 HTTPS 请求时,连接卡在 CONNECTING 状态 30 秒后超时。

环境信息

项目 版本
Workerman 最新版
Swoole 6.2.1
PHP 8.3+
框架 webman
运行环境 Docker

复现代码

php
use Workerman\Http\Client;

$client = new Client(['timeout' => 10]);
$client->request('https://reply.lsmir2.com/reply.php', [
    'method' => 'POST',
    'data'   => json_encode(['test' => true]),
    'success' => function($response) {
        echo $response->getBody()->getContents();
    },
    'error' => function($e) {
        echo "Error: " . $e->getMessage();
    },
]);

复现结果

  • 期望:HTTPS 请求成功,返回响应内容
  • 实际:连接卡在 CONNECTING 状态,30 秒后超时

诊断日志

[HTTP-Client][process] state before send=CONNECTING
[HTTP-Client][process] request sent
--- 30 秒后 ---
[AsyncTcp][checkConnection] called
[Swoole][callWrite] TRIGGERED! fd=244
[AsyncTcp][checkConnection] stream_socket_get_name='198.18.1.91:443'
[TcpConnection][doSslHandshake] stream_socket_enable_crypto returned=false

Swoole 内部 SSL 错误(Docker 日志):

ssl_connect(fd=12) failed. Error: error:0A0003E7:SSL routines::invalid session id

与官方修复的对比

官方 commit 1391112a61d23020e11e7b89f17050f6cfaea431 处理了返回 0(需要重试)的情况:

php
if ($this->sslHandshakeCompleted === 0) {
    $this->eventLoop->onReadable($this->socket, $this->checkConnection(...));
    $this->eventLoop->onWritable($this->socket, $this->checkConnection(...));
    return;
}

但当前问题返回 false(彻底失败),官方修复未覆盖此场景。

根因分析

层面 问题
Swoole SWOOLE_HOOK_STREAM_FUNCTION 对异步 socket SSL 握手实现有 bug,返回 invalid session id
Workerman 使用标准 PHP stream API,在 Swoole hook 环境下触发兼容问题

建议修复方向

  1. 短期:在文档中说明 Swoole 事件循环下 HTTPS 的兼容性问题,建议用户使用 Swoole\Coroutine\Http\Client
  2. 长期:考虑在 Swoole 事件循环下自动切换使用 Swoole 原生 HTTP 客户端

当前绕过方案

在应用层,HTTPS 请求改用 Swoole\Coroutine\Http\Client

php
use Swoole\Coroutine\Http\Client as SwooleHttpClient;

$client = new SwooleHttpClient($host, 443, true);
$client->setHeaders($this->headers);
$client->post($path, $data);
return new \Workerman\Http\Response($client->statusCode, $client->headers, $client->body);

验证通过:HTTPS 请求正常返回 success