Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Swoole 4.6.1、Swoole 5.1.6、Swoole 6.0.0 验证协程客户端PgSql 无异步效果(Swoole 4.6.1, Swoole 5.1.6, Swoole 6.0.0 verify that the coroutine client PgSql has no asynchronous effect) #5635

Open
yibin94 opened this issue Dec 24, 2024 · 16 comments

Comments

@yibin94
Copy link

yibin94 commented Dec 24, 2024

Please answer these questions before submitting your issue.

  1. What did you do? If possible, provide a simple script for reproducing the error.

Hyperf2.2项目,Swoole版本是4.8.11,需要使用协程客户端的PgSql,4.x版本需要额外编译swoole/ext-postgresql(最新版是v4.8.0),
于是另外找了个4.6.1的版本去验证协程效果,Swoole和ext-postgresql版本信息如下:
验证得出结论:4.6.1、5.1.6、6.0.0 都没有协程PgSql的异步效果,是同步阻塞,希望能得到解答,确认是我这边哪里疏忽还是说是bug

code: (Swoole 4.6.1、Swoole 5.1.6)

<?php

use Swoole\Coroutine;
use Swoole\Coroutine\PostgreSQL;
use function Swoole\Coroutine\run;

run(function () {
    for ($i = 1;$i <= 2;$i++) {
       Coroutine::create(function () use ($i) {
           $pg = new PostgreSQL();
           $conn = $pg->connect(sprintf(
              'host=%s port=%s dbname=%s user=%s password=%s',
              'xxx',
               5432,
              'xxx',
              'xxx',
              'xxx'
           ));
           if (!$conn) {
             var_dump($pg->error);
             return;
           }
           $stmt = $pg->query('SELECT * FROM tab  limit 3;');
           $arr = $pg->fetchAll($stmt);
           var_dump($i . ' :rows num=' . count($arr));
        });
   }
});
var_dump(666);
sleep(8);
var_dump(888);

code: (Swoole 5.1.6、Swoole 6.0.0)

<?php

use Swoole\Coroutine;
use function Swoole\Coroutine\run;

Coroutine::set(['hook_flags' => SWOOLE_HOOK_ALL]);
Coroutine::set(['trace_flags' => SWOOLE_HOOK_PDO_PGSQL]);
run(function () {
    for ($i = 1;$i <= 2;$i++) {
      Coroutine::create(function () use ($i) {
        $conn = new PDO(sprintf(
            "pgsql:dbname=%s;host=%s;port=%s",
            'xxx',
            'xxx',
            5432),
            'xxx',
            'xxx');
        if (!$conn) {
            var_dump($conn->error);
            return;
        }

        $stmt = $conn->query('SELECT * FROM tab limit 3;');
        $arr = $stmt->fetchAll();
        var_dump($i . ' :rows num=' . count($arr));
      });
    }
});
var_dump(666);
sleep(8);
var_dump(888);

  1. What did you expect to see?
    遇到数据库查询,先切换到外部协程打印数字,而不是一直阻塞等数据库查询返回结果。

  2. What did you see instead?

   string(13) "1 :rows num=3"
   string(13) "2 :rows num=3"
   int(666)
   int(888)
  1. What version of Swoole are you using (show your php --ri swoole)?

Swoole 4.6.1

Swoole => enabled
Author => Swoole Team <[email protected]>
Version => 4.6.1
Built => Jan 11 2021 12:29:13
coroutine => enabled with boost asm context
epoll => enabled
eventfd => enabled
signalfd => enabled
spinlock => enabled
rwlock => enabled
openssl => OpenSSL 1.1.1i  8 Dec 2020
dtls => enabled
http2 => enabled
json => enabled
curl-native => enabled
pcre => enabled
zlib => 1.2.11
mutex_timedlock => enabled
pthread_barrier => enabled
async_redis => enabled

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

php --ri swoole_postgresql

swoole_postgresql

Swoole PostgreSQL => enabled
Author => Swoole Team <[email protected]>
Version => 4.6.1
Built => Sep 17 2021 09:55:41
trace_log => enabled

Swoole 5.1.6 (dockerfile)

Swoole => enabled
Author => Swoole Team <[email protected]>
Version => 5.1.6
Built => Dec 24 2024 02:51:43
coroutine => enabled with boost asm context
epoll => enabled
eventfd => enabled
signalfd => enabled
spinlock => enabled
rwlock => enabled
sockets => enabled
openssl => OpenSSL 1.1.1w  11 Sep 2023
dtls => enabled
http2 => enabled
json => enabled
curl-native => enabled
pcre => enabled
zlib => 1.2.12
brotli => E16777225/D16777225
mutex_timedlock => enabled
pthread_barrier => enabled
mysqlnd => enabled
async_redis => enabled
coroutine_pgsql => enabled

Swoole 6.0.0 (dockerfile)

Swoole => enabled
Author => Swoole Team <[email protected]>
Version => 6.0.0
Built => Dec 24 2024 05:19:00
coroutine => enabled with boost asm context
epoll => enabled
eventfd => enabled
signalfd => enabled
spinlock => enabled
rwlock => enabled
openssl => OpenSSL 3.3.2 3 Sep 2024
dtls => enabled
http2 => enabled
json => enabled
mutex_timedlock => enabled
pthread_barrier => enabled
coroutine_pgsql => 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
  1. What is your machine environment used (show your uname -a & php -v & gcc -v) ?
   Swoole 4.6.1 环境下对应 php= PHP 7.4.13 (cli) (built: Dec 28 2020 05:26:43) ( NTS )
   Swoole 5.1.6 环境下对应 php = PHP 8.0.30 (cli) (built: Oct 21 2023 06:13:34) ( NTS )
   Swoole 6.0.0 环境下对应 php = PHP 8.1.31 (cli) (built: Dec 11 2024 23:33:39) (NTS)
@NathanFreeman
Copy link
Member

<?php

use Swoole\Coroutine;
use Swoole\Coroutine\PostgreSQL;
use function Swoole\Coroutine\run;

run(function () {
    for ($i = 1;$i <= 2;$i++) {
       Coroutine::create(function () use ($i) {
           $pg = new PostgreSQL();
           $conn = $pg->connect(sprintf(
              'host=%s port=%s dbname=%s user=%s password=%s',
              'xxx',
               5432,
              'xxx',
              'xxx',
              'xxx'
           ));
           if (!$conn) {
             var_dump($pg->error);
             return;
           }
           $stmt = $pg->query('SELECT * FROM tab  limit 3;');
           $arr = $pg->fetchAll($stmt);
           var_dump($i . ' :rows num=' . count($arr));
        });
   }
  var_dump(666);
  sleep(8);
  var_dump(888);
});

run函数内部才是协程环境,外部是非协程环境,所以先执行postgresql查询,执行完才会这行下面的逻辑,类似下面的执行。
只有run函数内部才会发生协程切换。
run();
var_dump(666);
sleep(8);
var_dump(888);

@yibin94
Copy link
Author

yibin94 commented Dec 25, 2024

你好!感谢解答,我上面测试示例写错了,然后按你说的将三行代码挪到run()内部,是可以切换,但效果不同,分别如下:

  1. 在Swoole 4.6.1 (使用Swoole\Coroutine\PostgreSQL)结果如下,发生 sleep 会先去执行 SQL 再回来打印888 (我在发送Query查询前打印了数据得出的执行顺序)
    int(666)
    string(13) "2 :rows num=3"
    string(13) "1 :rows num=3"
    int(888)
  1. 在Swoole 5.1.6 与 Swoole 6.0.0(使用 HOOK设置标记SWOOLE_HOOK_PDO_PGSQL + PDO)结果如下,先发生sleep会睡眠完毕,打印888,后去执行 SQL (我在发送Query查询前打印了数据得出的执行顺序)
    int(666)
    int(888)
    string(13) "1 :rows num=3"
    string(13) "2 :rows num=3"
  1. 其实我这边是有个场景需要处理:第三方的 PgSql 数据库偶发响应很久导致我这边设置的10秒超时(channel)停不掉该请求(其它接口都受影响),我是用 Hyperf 框架写的,转为 Swoole 代码如下:
  • 在Swoole 4.6.1 (使用Swoole\Coroutine\PostgreSQL)
<?php
use Swoole\Coroutine;
use Swoole\Coroutine\Channel;
use Swoole\Coroutine\PostgreSQL;
use function Swoole\Coroutine\run;

run( function() {
	$channel = new Channel(1);
	Coroutine::create(function () use ($channel) {
		$pg = new PostgreSQL();
		$conn = $pg->connect(sprintf(
		  'host=%s port=%s dbname=%s user=%s password=%s',
		  'xxx',
		  5432,
		  'xxx',
		  'xxx',
		  'xxx'
		));
		if (!$conn) {
		  var_dump($pg->error);
		  return;
		}
		$stmt = $pg->query('SELECT * FROM tab limit 3');
		$arr = $pg->fetchAll($stmt);
		var_dump('rows num=' . count($arr));
		$channel->push($arr ?? [], 10.0);
	});
	Coroutine::create(function () use ($channel) {
		$data = $channel->pop(10.0);
		var_dump('channel data: ' . count($data));
	});
	var_dump(1);
	Coroutine::sleep(4);
	var_dump(2);
});

结果:

int(1)
string(10) "rows num=3"
string(15) "channel data: 3"
int(2)

限制返回数据量的 SQL 正常如期响应,此时我模拟那种很久响应的场景==将 SQL 改成
$stmt = $pg->query('SELECT * FROM tab'); 效果会在输出 int(1) 后一直卡住,如下
int(1)
卡住等待数据库返回响应...

同理,我在Swoole 5.1.6 与 Swoole 6.0.0(使用 HOOK设置标记SWOOLE_HOOK_PDO_PGSQL + PDO),测试代码和结果如下

<?php
use Swoole\Coroutine;
use Swoole\Coroutine\Channel;
use function Swoole\Coroutine\run;

Coroutine::set(['hook_flags' => SWOOLE_HOOK_PDO_PGSQL]);
Coroutine::set(['trace_flags' => SWOOLE_HOOK_PDO_PGSQL]);
run( function() {
	$channel = new Channel(1);
	Coroutine::create(function () use ($channel) {
		$connection = new PDO(sprintf(
			"pgsql:dbname=%s;host=%s;port=%s",
			'xxx',
			'xxx',
			5432),
			'xxx',
			'xxx');
		$stmt = $connection->query('select * from tab');
		$arr = $stmt->fetchAll();
		$channel->push($arr ?? [], 10.0);
	});
	Coroutine::create(function () use ($channel) {
		$data = $channel->pop(10.0);
		var_dump('channel data: ' . count($data));
	});
	var_dump(1);
	Coroutine::sleep(4);
	var_dump(2);
});

结果
int(1)
卡住等待数据库返回响应...

帮忙再确认下当遇到这种响应很久的 SQL 时,$channel->pop($timeout)是否无法被执行到

@NathanFreeman
Copy link
Member

NathanFreeman commented Dec 25, 2024

$channel->pop($timeout)已经执行到了,只不过在等待postgresql返回结果

@yibin94
Copy link
Author

yibin94 commented Dec 25, 2024

假如执行到的话,正常逻辑不是会在 $timeout 到时就触发超时停止吗?目前就是卡住了,请问有办法处理吗?目前效果是一旦出现这种情况相当于,其它代码都执行不了了(无法响应)。

@NathanFreeman
Copy link
Member

strace -p 进程ID,查看一下当前进程在执行什么逻辑。

@NathanFreeman
Copy link
Member

php -m查看一下php的扩展列表

@yibin94
Copy link
Author

yibin94 commented Dec 25, 2024

  1. Swoole 4.6.1,php PHP 7.4.13
    php -m
[PHP Modules]
bcmath
Core
ctype
curl
date
dom
fileinfo
filter
gd
hash
iconv
json
libxml
mbstring
mysqlnd
openssl
pcntl
pcre
PDO
pdo_mysql
pdo_sqlite
Phar
posix
readline
redis
Reflection
session
SimpleXML
sockets
sodium
SPL
standard
swoole
swoole_postgresql
sysvmsg
sysvsem
sysvshm
tokenizer
xml
xmlreader
xmlwriter
Zend OPcache
zip
zlib

[Zend Modules]
Zend OPcache

strace -p $pid
返回内容过多,只取一部分

bash-5.0# strace -p 587
strace: Process 587 attached
restart_syscall(<... resuming interrupted read ...>) = 1
recvfrom(7, "4\0\266@\257\225\245\27\215\f6v\315r\263Z\21\215M$\203\373\312x\276t\252\313t6\200\304"..., 6332, 0, NULL, NULL) = 2756
recvfrom(7, 0x55f49f125e81, 3576, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=7, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=7, revents=POLLIN}])
recvfrom(7, "p\273\325\350\265\312\3172g\16*\32\313\334E\222\312\215\205\334/\30\355\345B\242\250\230\232\236\266~"..., 3576, 0, NULL, NULL) = 3576
brk(0x55f4a00eb000)                     = 0x55f4a00eb000
brk(0x55f4a00ec000)                     = 0x55f4a00ec000
brk(0x55f4a00ed000)                     = 0x55f4a00ed000
brk(0x55f4a00ee000)                     = 0x55f4a00ee000
poll([{fd=7, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=7, revents=POLLIN}])
recvfrom(7, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(7, "\377\352\256\261N\6kN\353\373\322\370\231\225\274\302\377.\301X\303\302G\363\2019B\334\26%Ap"..., 8209, 0, NULL, NULL) = 1931
recvfrom(7, 0x55f49f1253f3, 6278, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=7, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=7, revents=POLLIN}])
recvfrom(7, "{U1\371\261oEW\251MF\31\304\36\326\214,\350decf\261E\204b\306\240\247\345-4"..., 6278, 0, NULL, NULL) = 6278
brk(0x55f4a00ef000)                     = 0x55f4a00ef000
brk(0x55f4a00f0000)                     = 0x55f4a00f0000
brk(0x55f4a00f1000)                     = 0x55f4a00f1000
brk(0x55f4a00f2000)                     = 0x55f4a00f2000
poll([{fd=7, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=7, revents=POLLIN}])
recvfrom(7, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(7, "I\6\314\341K/G\352\2377l\214\206H;\221$\264\232\205)\t\256a^\2-\"\4\213\301W"..., 8209, 0, NULL, NULL) = 4741
recvfrom(7, 0x55f49f125eed, 3468, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=7, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=7, revents=POLLIN}])
recvfrom(7, "X\364\346\223,\335\353D\321\232\207\205\304Yo\332\4\264\274\35\200Pm3v\265]\3767\310\3+"..., 3468, 0, NULL, NULL) = 3468
brk(0x55f4a00f3000)                     = 0x55f4a00f3000
brk(0x55f4a00f4000)                     = 0x55f4a00f4000
brk(0x55f4a00f5000)                     = 0x55f4a00f5000
brk(0x55f4a00f6000)                     = 0x55f4a00f6000
brk(0x55f4a00f7000)                     = 0x55f4a00f7000

@yibin94
Copy link
Author

yibin94 commented Dec 25, 2024

  1. Swoole 5.1.6、PHP 8.0.30
    php -m
  [PHP Modules]
  Core
  ctype
  curl
  date
  dom
  fileinfo
  filter
  ftp
  hash
  iconv
  json
  libxml
  mbstring
  mysqlnd
  openssl
  pcre
  PDO
  pdo_mysql
  pdo_sqlite
  Phar
  posix
  readline
  redis
  Reflection
  session
  SimpleXML
  sockets
  sodium
  SPL
  sqlite3
  standard
  swoole
  tokenizer
  xml
  xmlreader
  xmlwriter
  zlib
  
  [Zend Modules]
  1. strace -p $pid
  strace: Process 91 attached
  restart_syscall(<... resuming interrupted read ...>) = 1
  recvfrom(4, "\267\315w\fX\332wz\26\340\3371\36\333\7@\224\363Q\37\3301M]\22\f\1\367N<p\207"..., 4924, 0, NULL, NULL) = 2756
  recvfrom(4, 0x7f6802154e51, 2168, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\2775\370\237\360y\253Z>Y\303\237\177j\\\23Iu\177\rF08R\260\223;|%(\335\261"..., 2168, 0, NULL, NULL) = 2168
  mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6801e0a000
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
  recvfrom(4, "\260\223PhI\307V\35E\300\2053\211\276s\374\17\353\373\276(\31\236\252\32\260'\215!4\235\375"..., 8209, 0, NULL, NULL) = 583
  recvfrom(4, 0x7f68021538ff, 7626, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\37QP=fL\200=+X\306\231k\312K\242\266\204\vj\262\2\354,\4\205p\362B\265\275\230"..., 7626, 0, NULL, NULL) = 5512
  recvfrom(4, 0x7f6802154e87, 2114, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "=!6O\2c \330\234\256Z\370nXb\203\322[\20\310\276\364\330\236\2\305\t\24\343\345x\301"..., 2114, 0, NULL, NULL) = 2114
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
  recvfrom(4, "\v\247\336\"\226\242T?\340\336\262\68e\336A\327\316\256T\303\27\234W\211$\320\203\275y:\246"..., 8209, 0, NULL, NULL) = 637
  recvfrom(4, 0x7f6802153935, 7572, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\177.\220\22Sp\236`\236\224[\26)\22C~{\217\253E\355\265\213(\375\370W\2v\230\275\202"..., 7572, 0, NULL, NULL) = 2756
  recvfrom(4, "\23\257\343\330dm]\204\27\214\313\2s\352A\251z\36w\314[H\231s\336b\311\257\17#\2025"..., 4816, 0, NULL, NULL) = 4816
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
  recvfrom(4, "\230\t\225\254b\2\230O\324\225$\244\25\264\251\fV\231\250\f[\346!r|\307\317\5\337\27\270<"..., 8209, 0, NULL, NULL) = 691
  recvfrom(4, 0x7f680215396b, 7518, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\360y7\rl\26_Kr\342\220\374P\317\2657\332\0y\342\227W\222\362\255-\310^\224\233\254B"..., 7518, 0, NULL, NULL) = 2756
  recvfrom(4, 0x7f680215442f, 4762, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\207\251\3230\200\201=\37\5w\3629\3\342\0226\\~}\25kG\367\372_G.\324}\326i'"..., 4762, 0, NULL, NULL) = 2756
  recvfrom(4, 0x7f6802154ef3, 2006, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "n1V\223\245#,-\251\236\214L?\251\347\326;\v\373EF\301\302u\330\205<8]\2611\220"..., 2006, 0, NULL, NULL) = 2006
  mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6801dfa000
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
  recvfrom(4, "\30A\24\313(\240\20K\242\372\313@=\35\335v\346<^\240.!\365\247\314\231\3555\332\202\260r"..., 8209, 0, NULL, NULL) = 3501
  recvfrom(4, 0x7f6802154465, 4708, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "_\333\0306\200\275=Z\243\260\213|\324Y\4\1\250G\251]\206o^\206\333\315\264\303\307\31y\244"..., 4708, 0, NULL, NULL) = 4134
  recvfrom(4, 0x7f680215548b, 574, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "_;.\342\344\26\363t\3648\307\221\211\350]\343X\2769J\307\226\351\"\f\310\5_oh \271"..., 574, 0, NULL, NULL) = 574
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
  recvfrom(4, "\262\351$\5\225\30\250-v\222IE{\364\10m\31\246li\274\236\257Y~\0$\370\207\23\257\273"..., 8209, 0, NULL, NULL) = 2177
  recvfrom(4, "\204rC\251x=8\245\27\344\206\377)fs\323\350\321D\32\343\306\346e\215%k\227\356\212\6\371"..., 6032, 0, NULL, NULL) = 2756
  recvfrom(4, "\377G\371\310{x\213\273\321K\344\251_\214U\21{\365)\301\337\303\t?\3263\304\374\10`\214\7"..., 3276, 0, NULL, NULL) = 2756
  recvfrom(4, 0x7f68021554c1, 520, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, ",lC\r\365\5*\22t\243O5r\377H\300\25\307y\30\230\25\5\311\3555%0\201Z\357\32"..., 520, 0, NULL, NULL) = 520
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
  recvfrom(4, "\367>[\16\206\t\325\327\234i\360tL\220\"\360\35\314\220\34R\260\306\271e\223\324 \2\362$7"..., 8209, 0, NULL, NULL) = 3609
  recvfrom(4, 0x7f68021544d1, 4600, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\362\223Q\21\222\316\267\363<\313[\3\300Z\33\351\237\231\222Q?Gf\34\334n\276\33\356&\33\351"..., 4600, 0, NULL, NULL) = 4600
  mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6801dea000
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
  recvfrom(4, "-GG(\275\217\35\1\223\234\205\3559\265\344\360\244\373\343m\f\214\221\375\364\234D,\366\35{("..., 8209, 0, NULL, NULL) = 907
  recvfrom(4, 0x7f6802153a43, 7302, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\25\251\177\21D\243\242\304\307#\371\375\250#\1\177\203\243\354\313o\354Y\7HB`\37\227#\22W"..., 7302, 0, NULL, NULL) = 2756
  recvfrom(4, 0x7f6802154507, 4546, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "3\272\301\10\2z\244\322IN\2736\33\6\361\3508*\316Y\300l\330\365\372q\367 \206DW^"..., 4546, 0, NULL, NULL) = 4134
  recvfrom(4, 0x7f680215552d, 412, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\346\304\3710\260\\\334\346\201Z\273\34\252\321\227\t\261\233f\220R\221\22\376\35\250\204\n\\Er\253"..., 412, 0, NULL, NULL) = 412
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
  recvfrom(4, "8h\341\342]1\f\236kA>p8\240\373\272*v+\266\t\233\222\5\372\263\331hA\261x "..., 8209, 0, NULL, NULL) = 7851
  recvfrom(4, 0x7f6802155563, 358, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\224\20\222M\31\21)\314\3>'\265\34R\320A\255\265(\333\24\343\346\214\343\317\2670\22\3104\272"..., 358, 0, NULL, NULL) = 358
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
  recvfrom(4, "\220\35\33p\255\244LW\211\373\305-\273\332;6\201\17\216k\377$\275:\204V\236\313B\n\340\306"..., 8209, 0, NULL, NULL) = 2393
  recvfrom(4, 0x7f6802154011, 5816, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\243\23\214\26\230\335r\370\2\224\330:\204\223Z\2222J\232{'k\35\31\242\371\201?%\224\315o"..., 5816, 0, NULL, NULL) = 5512
  recvfrom(4, 0x7f6802155599, 304, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\253\253\321:s\273\230&\253r\372\234\261\361K\3024\376X\344_s\263(\237y\352w\254\262G\215"..., 304, 0, NULL, NULL) = 304
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
  recvfrom(4, "eD\375e\345b\226\30;\360\326\314\355G:\231:6\310\277\345k\310\372\v\"\324qei\340\345"..., 8209, 0, NULL, NULL) = 2447
  recvfrom(4, 0x7f6802154047, 5762, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\273E\3026\347\264\322P\327\25\0s\354:Q/~\213\31I\223\216\0236\201w\361,{@y,"..., 5762, 0, NULL, NULL) = 5512
  recvfrom(4, 0x7f68021555cf, 250, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, ".Z\10\204Kp\347\n\234\241\30\365\326\212\217\364\302Foi\22\34'\21X\n+W>\376\334\366"..., 250, 0, NULL, NULL) = 250
  mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6801dda000
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
  recvfrom(4, "\354\326I\254\f\316\203\34\236hj\3\335\27\312\312\340\324\316\275^+K\177\276\262o\256\267\347\216\321"..., 8209, 0, NULL, NULL) = 8013
  recvfrom(4, 0x7f6802155605, 196, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "{[\3361? A71\342[o\301\376\30,F\311\337\301A\266\257\177\241~Y^3\"\2158"..., 196, 0, NULL, NULL) = 196
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
  recvfrom(4, "\246m\260\r\300`tj\307\314\273\303=\27\311\0\352\7\277?(?q\250\210\373\216 S;\323\1"..., 8209, 0, NULL, NULL) = 6689
  recvfrom(4, 0x7f68021550d9, 1520, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\364\10\203\275\271\321\336n\327\37\203\353\306\t\371\244\3571P\2562\312\201\201\337\372\326\361\326C\225k"..., 1520, 0, NULL, NULL) = 1520
  poll([{fd=4, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])
  recvfrom(4, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
  recvfrom(4, "\214\214l-S\216\v\351\1\0_\2655\202\305X\351z\330`\345\310\223s\272\277\"\352\23Q\277A"..., 8209, 0, NULL, NULL) = 1231
  recvfrom(4, 0x7f6802153b87, 6978, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
  1. Swoole 6.0.0、PHP 8.1.31
    php -m
  [PHP Modules]
  Core
  ctype
  curl
  date
  dom
  fileinfo
  filter
  ftp
  hash
  iconv
  json
  libxml
  mbstring
  mysqlnd
  openssl
  pcre
  PDO
  pdo_mysql
  pdo_pgsql
  pdo_sqlite
  Phar
  posix
  readline
  redis
  Reflection
  session
  SimpleXML
  sockets
  sodium
  SPL
  sqlite3
  standard
  swoole
  tokenizer
  xml
  xmlreader
  xmlwriter
  zlib
  
  [Zend Modules]
  1. strace -p $pid
   strace: Process 10334 attached
restart_syscall(<... resuming interrupted read ...>) = 1
recvfrom(5, "\24$\233_\375\303\211Y\231 \373\223\277c\1\331\337\204\327\362\3179\231\221\300DK\330\220U\210!"..., 4406, 0, NULL, NULL) = 4406
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "*\333\375i\1\33,\331\\\0263\20\325#\243_\372]\310/\310\255\242\275n\376\324\276\31\236I\267"..., 8209, 0, NULL, NULL) = 8209
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "b\303,\326\205\331&.\240\233\320CO\n\326$\223i\312U\373Zt\350h\7\35\364!g\33\t"..., 8209, 0, NULL, NULL) = 8209
mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3c8cc4c000
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "\37\342\\[\212\361+\350%o\266\2203J\207Y\32\222\353\302\254hT\317\372\321Z\240\371+\10\n"..., 8209, 0, NULL, NULL) = 8209
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "ze\32\377\231v\202\255\31\366\0\337]\342\237\376\245\241\247\341\352P\344\247\265\346\204\275\374\304'e"..., 8209, 0, NULL, NULL) = 8209
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "\230a\330\3277-|\10\354/\232\335\226\331\307?\3227c\202 \241\353\370\263\275\343\316\371\32\35X"..., 8209, 0, NULL, NULL) = 2695
recvfrom(5, 0x7f3c8dba5aff, 5514, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\260\201\276f\252NR\356.u\300\5\30\345\257J6\322#6\201\232~\24\253\4\f<\317\335\355n"..., 5514, 0, NULL, NULL) = 5514
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "\333\202w\230\27;\272\200M\366\327\220/\34\207\224\240\361\326n\203\354\206\34\370\26\253U@\f\255_"..., 8209, 0, NULL, NULL) = 8209
brk(0x55bf3ff20000)                     = 0x55bf3ff20000
mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3c8cc3c000
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "\16\351\10=\26\275\207\5\350\206\245\263\275h\373\r\304\270U\355k\0\10\250U\237a+jV\311,"..., 8209, 0, NULL, NULL) = 8209
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "\335\343\255\24\226\217Ew\208\241yWz}2\22&\260\f\373nJ\235(\265o\30\244&\214d"..., 8209, 0, NULL, NULL) = 8209
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "\f\316\34*\201\3658\242\276;\362\372Ry\246M+ \371\261\5\356:\3\33\311\304\361\212\344\335\225"..., 8209, 0, NULL, NULL) = 8209
mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3c8cc2c000
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "\26\304'`l\336\332^\243F\223\277a-\257\246f\207\354\351/\1\265m\302\333\313\203\343\317\0374"..., 8209, 0, NULL, NULL) = 8209
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "\212d\203\257\215\0q`I}\244\357\305\6\205GQz2-@8R\334\230\36C\21) 1\221"..., 8209, 0, NULL, NULL) = 8209
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "@>\257ud\353(\1a6\f\260\234\230\302\210\302\227\365\3261\337\250\223\27\326-\350\\\246\34\213"..., 8209, 0, NULL, NULL) = 8209
mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3c8cc1c000
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "\17\21\245\tX:I\234K\370\336\312\264=2D:\254\221N\356\325L\263\16Y\4AM\347|\26"..., 8209, 0, NULL, NULL) = 8209
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "\30\22#\372\215\31w\350\351\353\215\2532\261D\372-\275\370L\32\nf\311{\200\244(\310U~V"..., 8209, 0, NULL, NULL) = 1803
recvfrom(5, 0x7f3c8dba5783, 6406, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\203\301y5\232\232\210\246]\16\316\255(^H\215\35~\266\332\335\344\242\326YM\333L\215\235\335\232"..., 6406, 0, NULL, NULL) = 6406
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "\230\356\322\247\267\324^e\37}?\2313\7x\366z\314\322\263\360`\256\363\332\322s\235\236\212\31y"..., 8209, 0, NULL, NULL) = 8209
mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3c8cc0c000
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "\22\377\333\216\246\270mt\177\233\213\306\305\350\300\366O\337\310i\362\304/XJ\r\302G^\317\272\r"..., 8209, 0, NULL, NULL) = 7423
recvfrom(5, 0x7f3c8dba6d77, 786, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "9+\367\272\354\21#w\222W\375j\252B\324\25\va\361\177\200\230\211\10\344\344U\256q\351w\256"..., 786, 0, NULL, NULL) = 786
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "`\307\220\225\320\302\1\314\324\21Kk\177\366\260\21\251+~\233\16\222\\\346*\220\373\16\311\20x\360"..., 8209, 0, NULL, NULL) = 4721
recvfrom(5, 0x7f3c8dba62e9, 3488, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "W\n\362\263?YY\327f\353U\23\335S25\232\360U\246\207\222\207jP\216\325\363)\3616Y"..., 3488, 0, NULL, NULL) = 3488
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "\365{s\33m\2163Pz%`O\24\253!\222<\307\33B\240\374\205\10\20b\375\27\241#\331)"..., 8209, 0, NULL, NULL) = 4775
recvfrom(5, 0x7f3c8dba631f, 3434, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\n\354/\223|Um\335\306_1\3416N\217\230FV~?\227\307\300\354\244\377\370\232!\rU\273"..., 3434, 0, NULL, NULL) = 3434
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "\264\225mu\300\5G\243\342/\310]\23\347\372\230\231\24\34\244\320\271\321\r\7\320\345\232\263\17\346\347"..., 8209, 0, NULL, NULL) = 3451
recvfrom(5, 0x7f3c8dba5df3, 4758, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\33\370?\366\3605\316mm\315\236\215\256\264\202E\358\323\321\263\247\375l\257\267J\231 \232\301L"..., 4758, 0, NULL, NULL) = 4758
mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3c8cbfc000
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "\266\370q\325)\315\223H34\266>\377/\304,\250\377\22^\23F'\373\204\216\322\352N\20\202N"..., 8209, 0, NULL, NULL) = 2127
recvfrom(5, 0x7f3c8dba58c7, 6082, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "x\244Y[$\262\215\371\225n\224\311I\320YF;\215\374\234xM\320\235\20\223\365/\316 \256\r"..., 6082, 0, NULL, NULL) = 6082
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "\253\237o\261y\201\250P\323jB\3112\222Y\3026\227m\n\203\261\320K%\232\220\4\24A\251\364"..., 8209, 0, NULL, NULL) = 3559
recvfrom(5, 0x7f3c8dba5e5f, 4650, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\341U\32\300\325U\301&\215\354O\207\243y\305\rMm\275\365,G\253\211\17\267\344\344)\3\234\263"..., 4650, 0, NULL, NULL) = 4650
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "\371^\262g/\330\357\236-%\335z\256\10X\24{\177\234a1\204\30D}x\270E\275\247#."..., 8209, 0, NULL, NULL) = 8209
mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3c8cbec000
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "\\\364\20\355.[e\357\352xS\336\352\225\335\301\37g\335\306|\204\177\211\302\216\302\36\24\25f\301"..., 8209, 0, NULL, NULL) = 8209
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "\27\3\3 \21", 5, 0, NULL, NULL) = 5
recvfrom(5, "\v`U\254\252$B)c\363q\275]s\335\314\254\255M\21j\336\341M\"\306\221\363\32\323a\357"..., 8209, 0, NULL, NULL) = 8209

@NathanFreeman
Copy link
Member

NathanFreeman commented Dec 25, 2024

#5637 测试是没什么问题的

有一种可能是你的程序在不断地从postgresql获取数据,这个时候的文件描述符都是可读可写的,此时是不会发生协程切换的。
你可以试试不用fetchAll,使用fetch一行行获取数据并放入channel中,或者尝试配置enable_preemptive_scheduler,让swoole强制让出协程。

@matyhtf
Copy link
Member

matyhtf commented Dec 26, 2024

这应该是 hook 不生效导致的,你需要检查一下扩展加载顺序,swoole 扩展要晚于 pdo_pgsql 被加载。或者直接禁用 pdo_pgsql 扩展

@matyhtf matyhtf closed this as completed Dec 26, 2024
@yibin94
Copy link
Author

yibin94 commented Dec 26, 2024

回复 @NathanFreeman

  1. 首先感谢你这边验证,然后我这边按你测试用例的 pg_sleep() 函数去测试,即使是调到 60 秒都没问题的(即可以正常切换协程==效果是到点停止 $channel->pop(几秒都行))
  2. 我这边是为了模拟线上的第三方 PgSql 偶发无响应(可能是他们自己触发的数据库锁,这种就不好复现),导致影响所有接口(包括非数据库业务的接口),所以我就查询全表来模拟这种场景的复现,Navicat 查询耗时是1分钟多一点响应100w+数据的
  3. 当我运行 fetchAll 的代码一直等到最后是会报错内存不足,也说明了fetchAll 确实是在不断读取数据
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes) in /var/www/channel.php on line 19
[2024-12-26 02:04:16 @10359.0]  WARNING Channel::~Channel() (ERRNO 10003): channel is destroyed, 1 consumers will be discarded
  1. 接着按你说的改成 pdo 的 fetch 游标形式循环读入 channel ,发现当查全表的时候还是阻塞(加上Limit是正常依次读并获取数据打印),无法打印channel的数据,另一个等待的 channel 也无法正常停止
  2. 开启 http 服务去设置 enable_preemptive_scheduler ,验证情况:读全表的数据操作无法切换协程;随便开2个协程模拟sleep操作,可以正常交替运行
  3. 猜测:数据查询操作可能是同步的,只是查少量数据就较快能得到数据,没验出这种场景

回复 @matyhtf
感谢答复,我昨天验证情况中,Swoole 5.1.6 的php -m 是没有 pdo_pgsql 扩展的;今天按你说的把 Swoole 6.0.0 的 pdo_pgsql 扩展禁用,再验证也是一样的效果。

@matyhtf matyhtf reopened this Dec 26, 2024
@matyhtf
Copy link
Member

matyhtf commented Dec 26, 2024

@yibin94 你试试在阻塞的时候,使用 gdb -p PID 追踪进程,然后使用 bt 指令打印一下进程在哪段代码中发生了阻塞循环

@yibin94
Copy link
Author

yibin94 commented Dec 26, 2024

@matyhtf 你好,以下是Swoole 6.0.0 执行gdb -p $pid, bt 指令执行后的打印内容

(gdb) bt
#0  __cp_end () at src/thread/x86_64/syscall_cp.s:29
#1  0x00007fb7f38f7617 in __syscall_cp_c (nr=7, u=<optimized out>, v=<optimized out>, w=<optimized out>,
    x=<optimized out>, y=<optimized out>, z=0) at src/thread/pthread_cancel.c:33
#2  0x00007fb7f38e94dc in poll (fds=<optimized out>, n=<optimized out>, timeout=<optimized out>)
    at src/select/poll.c:9
#3  0x00007fb7f23ae3da in ?? () from /usr/lib/libpq.so.5
#4  0x00007fb7f23ae4a0 in ?? () from /usr/lib/libpq.so.5
#5  0x00007fb7f23aab53 in PQgetResult () from /usr/lib/libpq.so.5
#6  0x00007fb7f24c8ee3 in swoole_pgsql_exec_prepared ()
   from /usr/local/lib/php/extensions/no-debug-non-zts-20210902/swoole.so
#7  0x00007fb7f25e1664 in ?? () from /usr/local/lib/php/extensions/no-debug-non-zts-20210902/swoole.so
#8  0x000055a9b77a5fbb in ?? ()
#9  0x000055a9b7995952 in execute_ex ()
#10 0x000055a9b791b83f in zend_call_function ()
#11 0x00007fb7f24f7d9c in swoole::PHPCoroutine::main_func(void*) ()
   from /usr/local/lib/php/extensions/no-debug-non-zts-20210902/swoole.so
#12 0x00007fb7f25417a4 in swoole::coroutine::Context::context_func(transfer_t) ()
   from /usr/local/lib/php/extensions/no-debug-non-zts-20210902/swoole.so
#13 0x00007fb7f25e17ef in swoole_make_fcontext ()
   from /usr/local/lib/php/extensions/no-debug-non-zts-20210902/swoole.so
#14 0x0000000000000000 in ?? ()

@NathanFreeman
Copy link
Member

你的全表大概有多少数据,可以的话,能贴一下这张表的定义吗

@yibin94
Copy link
Author

yibin94 commented Dec 26, 2024

@NathanFreeman
第三方 PgSql 提供到这边的查询对象是视图,大数据量有 100 w+,小的有 12.9 w,其实数据量还好,只是那边返回数据的时间不是稳定的,比如说早上我查 100 w+ 的全表需要 1 分多钟,现在查前 1 w(limit 10000)都需要 140 s,所以我需要处理这种异常情况,设置个最大等待响应的时间,而不是一直等响应,不然就会整个进程都无法响应其它请求

其中一个表(12.9 w 数据量)的定义如下

"column_name"	"data_type"	"is_nullable"	"column_default"
"id"	    "bigint"	"YES"	
"stop_id"	"text"	"YES"	
"stop_name"	"USER-DEFINED"	"YES"	
"image_url"	"text"	"YES"	
"lat"	"numeric"	"YES"	
"lon"	"numeric"	"YES"	
"location"	"USER-DEFINED"	"YES"	
"type_id"	"smallint"	"YES"	
"template"	"USER-DEFINED"	"YES"	
"target"	"smallint"	"YES"	
"conditions"	"jsonb"	"YES"	
"rewards"	"jsonb"	"YES"	
"timestamp"	"timestamp with time zone"	"YES"	
"first_added"	"timestamp with time zone"	"YES"	
"first_seen"	"timestamp with time zone"	"YES"	
"modified"	"timestamp with time zone"	"YES"	
"last_received"	"timestamp with time zone"	"YES"	
"ar_scan_eligible"	"boolean"	"YES"	
"with_ar"	"boolean"	"YES"	
"title"	"USER-DEFINED"	"YES"	

@NathanFreeman
Copy link
Member

找到原因了,我晚上提交个PR修复它

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants