首页
下载
文档
社区
视频
捐赠
源代码
赞助商
AOT 编译器
AI 助理
商业产品
PHP AOT 原生编译器
Swoole-Compiler 代码加密器
CRMEB 新零售社交电商系统
登录
注册
全部
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
发表新帖
Channel实现的协程版TcpClient连接池无法复用
### 问题描述 Channel实现的协程版TcpClient连接池无法复用, 如代码中, 只能成功send与recv 16次, 之后重新从channel push 再pop的连接实例无法正常send, 不知道什么原因 ### Swoole版本,PHP版本,以及操作系统版本信息 ```bash swoole Swoole => enabled Author => Swoole Team <team@swoole.com> Version => 4.4.18 Built => Apr 30 2020 19:27:06 coroutine => enabled epoll => enabled eventfd => enabled signalfd => enabled spinlock => enabled rwlock => enabled sockets => enabled http2 => enabled pcre => enabled zlib => 1.2.11 mutex_timedlock => enabled pthread_barrier => enabled futex => enabled mysqlnd => 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 => On => On swoole.unixsock_buffer_size => 8388608 => 8388608 ``` ### 相关代码 ```php <?php use Swoole\Coroutine\Channel; use Swoole\Coroutine\Client; use Swoole\Coroutine\Server; use Swoole\Process; function run() { $process = new Process(function () { $server = new Server('unix:/var/run/rpc.sock', 0); // $server = new Server('0.0.0.0', 9505); //收到15信号关闭服务 Process::signal(SIGTERM, function () use ($server) { $server->shutdown(); }); $server->handle(function (Server\Connection $connection) { try { $requestData = $connection->recv(); var_dump('receive', $requestData); $connection->send($requestData); } catch (Throwable $exception) { echo "RpcException {$exception->getMessage()}\n"; } }); $server->start(); }, 0, 1, true); $process->start(); usleep(100000); for ($i = 0; $i < 200; $i ++ ) { go(function () { clientTest(); }); } } function clientTest() { // $instance = new Client(SWOOLE_SOCK_UNIX_STREAM); // $instance->connect(RpcUtility::DEFAULT_TCP_HOST, 0); $instance = simplePool()->pop(); $rand = mt_rand(); var_dump('send', $rand); if (! $instance->send($rand)) { var_dump('err', $rand, $instance->errMsg, $instance->errCode); } $response = $instance->recv(-1); if ($instance->errCode > 0) { // var_dump('err', $instance->errMsg, $instance->errCode); } var_dump('result', $response); simplePool()->push($instance); // $instance->close(); } function simplePool() : Channel { static $pool = null; if (null === $pool) { $pool = new Channel(100); for ($i = 0; $i < 16; $i ++) { $instance = new Client(SWOOLE_SOCK_UNIX_STREAM); // $instance = new Client(SWOOLE_SOCK_UDP); $instance->connect('/var/run/rpc.sock', 0); // $instance->connect('0.0.0.0', 9505); $pool->push($instance); } } return $pool; } run(); ``` ### 你期待的结果是什么?实际看到的错误信息又是什么? 希望能一直反复利用, 200个循环全部成功, 但实际上每个连接用了一次就失效或断开了
发布于6年前 · 1 次浏览 · 来自
提问
Drunk
### 问题描述 Channel实现的协程版TcpClient连接池无法复用, 如代码中, 只能成功send与recv 16次, 之后重新从channel push 再pop的连接实例无法正常send, 不知道什么原因 ### Swoole版本,PHP版本,以及操作系统版本信息 ```bash swoole Swoole => enabled Author => Swoole Team <team@swoole.com> Version => 4.4.18 Built => Apr 30 2020 19:27:06 coroutine => enabled epoll => enabled eventfd => enabled signalfd => enabled spinlock => enabled rwlock => enabled sockets => enabled http2 => enabled pcre => enabled zlib => 1.2.11 mutex_timedlock => enabled pthread_barrier => enabled futex => enabled mysqlnd => 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 => On => On swoole.unixsock_buffer_size => 8388608 => 8388608 ``` ### 相关代码 ```php <?php use Swoole\Coroutine\Channel; use Swoole\Coroutine\Client; use Swoole\Coroutine\Server; use Swoole\Process; function run() { $process = new Process(function () { $server = new Server('unix:/var/run/rpc.sock', 0); // $server = new Server('0.0.0.0', 9505); //收到15信号关闭服务 Process::signal(SIGTERM, function () use ($server) { $server->shutdown(); }); $server->handle(function (Server\Connection $connection) { try { $requestData = $connection->recv(); var_dump('receive', $requestData); $connection->send($requestData); } catch (Throwable $exception) { echo "RpcException {$exception->getMessage()}\n"; } }); $server->start(); }, 0, 1, true); $process->start(); usleep(100000); for ($i = 0; $i < 200; $i ++ ) { go(function () { clientTest(); }); } } function clientTest() { // $instance = new Client(SWOOLE_SOCK_UNIX_STREAM); // $instance->connect(RpcUtility::DEFAULT_TCP_HOST, 0); $instance = simplePool()->pop(); $rand = mt_rand(); var_dump('send', $rand); if (! $instance->send($rand)) { var_dump('err', $rand, $instance->errMsg, $instance->errCode); } $response = $instance->recv(-1); if ($instance->errCode > 0) { // var_dump('err', $instance->errMsg, $instance->errCode); } var_dump('result', $response); simplePool()->push($instance); // $instance->close(); } function simplePool() : Channel { static $pool = null; if (null === $pool) { $pool = new Channel(100); for ($i = 0; $i < 16; $i ++) { $instance = new Client(SWOOLE_SOCK_UNIX_STREAM); // $instance = new Client(SWOOLE_SOCK_UDP); $instance->connect('/var/run/rpc.sock', 0); // $instance->connect('0.0.0.0', 9505); $pool->push($instance); } } return $pool; } run(); ``` ### 你期待的结果是什么?实际看到的错误信息又是什么? 希望能一直反复利用, 200个循环全部成功, 但实际上每个连接用了一次就失效或断开了
赞
0
收藏
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
登录
后参与评论
评论
2020-05-20
Twosee
协程的正确写法: ```php Co\Run(function () { $server = new Server('unix:/tmp/swoole-test.sock', 0); $server->handle(function (Server\Connection $connection) { try { while (true) { $requestData = $connection->recv(); if ($err) break; // or throw exception $connection->send($requestData); if ($err) break; // or throw exception } } catch (Throwable $exception) { echo "RpcException {$exception->getMessage()}\n"; } }); $server->start(); }); ``` 此回调相当于onConnect, 需要自己对连接进行循环读写, 否则回调执行完后连接对象会被析构
赞
1
回复
2020-05-20
Drunk
回复
Twosee
谢谢大佬, 帮我解决了我折腾了两天的问题!
赞
0
回复