Skip to content

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

Description

@21307369

问题描述

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

环境信息

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

复现代码

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(需要重试)的情况:

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

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions