Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

Swoole HTTPS keep-alive 响应内容较大时,会出现最后一段数据需要在链接断开时才会触发事件回调的情况

未关闭
#39 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
35/100
Issue 类型
缺陷
描述清晰度
基本清楚
活跃度
停滞
技术栈
php
领域
networking

调研方向

使用 issue 中的示例重现 keep-alive 请求,然后检查 \Workerman\Events\Swoole::callRead() 以及围绕缓冲响应数据的 Swoole 事件处理。将 keep-alive 与 Connection: close 进行比较,并添加一个回归测试,证明最后一个小数据块会触发进度和成功,而无需等待连接关闭或超时。

由索引模型根据 Issue 内容生成。

描述

代码如下:

$connection = $request->connection;

$client = new Client([
      'max_conn_per_addr' => 128, // 每个域名最多维持多少并发连接
      'keepalive_timeout' => 30,  // 连接多长时间不通讯就关闭
      'connect_timeout'   => 5,   // 连接超时时间
      'timeout'           => 120,  // 请求发出后等待响应的超时时间
  ]);

$client->request('https://app.unpkg.com/vue@3.5.17/files/dist/vue.esm-browser.js', [
    'method' => 'GET',
    'version' => '1.1',
    'headers' => ['Connection' => 'keep-alive'],
    'progress' => function($buffer) use ($connection) {
          $connection->send(new Chunk(time()." 响应大小: " . strlen($buffer).PHP_EOL));
    },
    'success' => function($response) use ($connection) {
          $connection->send(new Chunk(time()." 响应成功"));
          $connection->send(new Chunk('')); // 发送空的的chunk代表response结束
    },
    'error' => function (\Throwable $exception) use ($connection) {
        $connection->send(new Chunk(time()." 响应失败: ".$exception->getMessage()));
        $connection->send(new Chunk(''));
    },
]);

return new Response(200, ["Transfer-Encoding" => "chunked"], '');

请求的这个 js 文件大小为 535 kB,由于开启了 keepalive,所以服务器会保持链接 60s,此时会出现能正常速度的输出很大一部分的响应大小,然后在最后一点内容的时候会一直 hang 住,直到链接被服务器关闭,才能正常的输出响应成功,或者是读取超时被 ConnectionPool 主动断开,如下所示:

....
1750845988 响应大小: 8192
1750845988 响应大小: 8192
1750845988 响应大小: 8192
1750846107 响应失败: read 104.18.0.22:443 timeout after 120 seconds

但如果将headers中的Connection设置为close,即:

'headers' => ['Connection' => 'close'],

此时再请求就会很正常的完成输出:

...
1750845798 响应大小: 8192
1750845798 响应大小: 8192
1750845798 响应大小: 7295
1750845798 响应成功

环境:

> php -v
PHP 8.2.8 (cli) (built: Jul 10 2023 23:07:42) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.8, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.8, Copyright (c), by Zend Technologies

> php --ri swoole

swoole

Swoole => enabled
Author => Swoole Team <team@swoole.com>
Version => 6.0.2
Built => Jun 25 2025 10:47:55
coroutine => enabled with boost asm context
epoll => enabled
eventfd => enabled
signalfd => enabled
cpu_affinity => enabled
spinlock => enabled
rwlock => enabled
sockets => enabled
openssl => OpenSSL 3.1.8 11 Feb 2025
dtls => enabled
http2 => enabled
json => enabled
curl-native => enabled
curl-version => 8.12.1
c-ares => 1.19.1
zlib => 1.2.13
brotli => E16777225/D16777225
zstd => 1.5.5
mutex_timedlock => enabled
pthread_barrier => enabled
futex => enabled
mysqlnd => enabled
io_uring => enabled

Directive => Local Value => Master Value
swoole.enable_library => On => On
swoole.enable_fiber_mock => Off => Off
swoole.enable_preemptive_scheduler => Off => Off
swoole.display_errors => On => On
swoole.use_shortname => On => On
swoole.unixsock_buffer_size => 8388608 => 8388608

根据代码追踪,可以确认是\Workerman\Events\Swoole::callRead()方法没有被触发,表现就是最后一段响应长度较小,未能出发 Swoole Event 的可读事件,导致这一部分数据一直在 buffer 中,无法被 PHP 代码读取。具体原因受限于我的知识面,无法深入了解了。

主要语言
PHP
星标
55
派生
19
PR 合并指标
30 天内没有已合并 PR

贡献指南

这个仓库没有索引到贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

workerman-php/http-client 的其他 Issue

查看 workerman-php/http-client 的全部 Issue

相似的 Issue

更多 PHP Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。