swoole / swoole-src

🚀 Coroutine-based concurrency library for PHP
https://www.swoole.com
Apache License 2.0
18.27k stars 3.16k forks source link

Swoole 4.2.3 Task中使用协程MySQL报错 #2041

Closed hhxsv5 closed 5 years ago

hhxsv5 commented 5 years ago

Please answer these questions before submitting your issue. Thanks!

  1. What did you do? If possible, provide a simple script for reproducing the error. Swoole 4.2.3 Task中使用协程MySQL报错
$swoole_mysql = new \Swoole\Coroutine\MySQL();
$swoole_mysql->connect([
    'host'     => 'mysql',
    'port'     => 3306,
    'user'     => 'root',
    'password' => 'abc123',
    'database' => 'test',
]);
$res = $swoole_mysql->query('select sleep(1)');
var_dump($res);
  1. What did you expect to see? 正常执行协程MySQL

  2. What did you see instead?

    [2018-10-16 18:48:24 ^369.1]    ERROR   zm_deactivate_swoole (ERROR 503): Fatal error: App\Tasks\TestTask::handle(): must be called in the coroutine. in /docker/www/laravel-s-test/app/Tasks/TestTask.php on line 29.
    [2018-10-16 18:48:24 $367.0]    WARNING swManager_check_exit_status: worker#1 abnormal exit, status=255, signal=0
  3. What version of Swoole are you using (show your php --ri swoole)? 4.2.3

  4. What is your machine environment used (including version of kernel & php & gcc) ? Debian GNU/Linux 8 \n \l PHP 7.1.21 (cli) (built: Sep 7 2018 22:17:18) ( NTS ) gcc version 4.9.2 (Debian 4.9.2-10+deb8u1)

twose commented 5 years ago

用go方法创建协程再使用,允许使用但不是自动创建协程。

hhxsv5 commented 5 years ago

谢谢,明白了。

另外Task中支持协程Runtime吗?

hhxsv5 commented 5 years ago

尝试在Task中开启Runtime,但报错了。

//Task中
\Swoole\Runtime::enableCoroutine();
$pdo = new \PDO('mysql:dbname=test;host=mysql', 'root', 'abc123');
$sql = sprintf('insert into test(name,created_at,updated_at) values("%s","%s","%s")', uniqid(), date('Y-m-d H:i:s'), date('Y-m-d H:i:s'));
$ret = $pdo->exec($sql);
var_dump($ret);
[2018-10-16 19:26:13 ^828.1]    WARNING yield: Socket::yield() must be called in the coroutine.
[2018-10-16 19:26:13 $826.0]    WARNING swManager_check_exit_status: worker#1 abnormal exit, status=0, signal=11
A bug occurred in Swoole-v4.2.3, please report it.
The Swoole developers probably don't know about it,
and unless you report it, chances are it won't be fixed.
You can read How to report a bug doc before submitting any bug reports:
>> https://github.com/swoole/swoole-src/issues/2000
Please do not send bug reports in the mailing list or personal letters.
The issue page is also suitable to submit feature requests.
twose commented 5 years ago

@hhxsv5 涉及协程的都需要在go中, 除非是支持自动化协程的回调. 可以通过 co::getuid 是否为 大于0 的数字 来判断是否在协程中 这里底层缺少了检测, 所以出错了

xiangjihan commented 5 years ago

现在搞不清楚,哪些地方是自动创建协程的,哪些需要手动创建。

hhxsv5 commented 5 years ago

@xiangjihan 根据文档,swoole_server和swoole_http_server将为每一个请求创建对应的协程,可以在onRequet、onReceive、onConnect中使用,其他地方都需手动创建协程, @twose 我的理解是否正确?

hhxsv5 commented 5 years ago

测试了下,在Task中使用启用协程Runtime,第一次执行成功,第二次开始报错。

go(function () {
    \Swoole\Runtime::enableCoroutine(); #注释掉这行就正常
    $pdo = new \PDO('mysql:dbname=test;host=mysql', 'root', 'abc123');
    $sql = sprintf('insert into test(name,created_at,updated_at) values("%s","%s","%s")', uniqid(), date('Y-m-d H:i:s'), date('Y-m-d H:i:s'));
    $ret = $pdo->exec($sql);
    var_dump($ret);
});
  [Symfony\Component\Debug\Exception\FatalErrorException]
  Uncaught ErrorException: PDO::exec(): MySQL server has gone away in /docker/www/laravel-s-test/app/Tasks/TestTask.php:47
  Stack trace:
  #0 [internal function]: Illuminate\Foundation\Bootstrap\HandleExceptions->handleError(2, 'PDO::exec(): My...', '/docker/www/lar...', 47, Array)
  #1 /docker/www/laravel-s-test/app/Tasks/TestTask.php(47): PDO->exec('insert into tes...')
  #2 {main}
    thrown
twose commented 5 years ago

@hhxsv5 理解正确, 稍后我添加一个相关单元测试 关于自动创建协程的范围: https://wiki.swoole.com/wiki/page/949.html

hhxsv5 commented 5 years ago

@twose 上面那个报错是怎么回事啊

twose commented 5 years ago

@hhxsv5 断线了需要重新创建连接

hhxsv5 commented 5 years ago

我是worker和task worker数都置为1,投递了三次任务,任务中go开协程连接数据库执行sql,第二次任务开始就报MySQL server has gone away。 这不科学,每次任务都是新协程、新数据库连接。 @twose

twose commented 5 years ago

@hhxsv5 可以贴一下简单的代码复现这个问题吗, 我这边尝试复现一下.

hhxsv5 commented 5 years ago

😢github 出bug了,贴了N次,贴不上。

tracy-ling commented 5 years ago

@twose

<?php
$http = new swoole_http_server('127.0.0.1', 5200);
$http->set([
    'daemonize'       => false,
    'worker_num'      => 1,
    'task_worker_num' => 1,
]);
$http->on('Request', function (swoole_http_request $request, swoole_http_response $response) use ($http) {
    $taskId = $http->task('run');
    $response->end('Hello LaravelS #' . $taskId);
});
$http->on('Task', function (swoole_http_server $server, $taskId, $srcWorkerId, $data) {
    go(function () {
        \Swoole\Runtime::enableCoroutine(); #注释掉这行就正常
        $pdo = new PDO('mysql:dbname=test;host=127.0.0.1', 'root', 'xy123456');
        $sql = sprintf('insert into test(name,created_at,updated_at) values("%s","%s","%s")', uniqid(),
            date('Y-m-d H:i:s'), date('Y-m-d H:i:s'));
        $pdo->exec($sql);
        var_dump($pdo->lastInsertId());
    });
});
$http->on('Finish', function (swoole_http_server $server, $taskId, $data) {

});
$http->start();
→ php task.php
PHP Warning:  Unknown: onTask handler error. in Unknown on line 0

Warning: Unknown: onTask handler error. in Unknown on line 0
PHP Fatal error:  Uncaught PDOException: PDO::__construct(): MySQL server has gone away in /Users/dave/Documents/docker/www/laravel-s-test/task.php:15
Stack trace:
#0 /Users/dave/Documents/docker/www/laravel-s-test/task.php(15): PDO->__construct('mysql:dbname=te...', 'root', 'xy123456')
#1 {main}

Next PDOException: SQLSTATE[HY000] [2006] MySQL server has gone away in /Users/dave/Documents/docker/www/laravel-s-test/task.php:15
Stack trace:
#0 /Users/dave/Documents/docker/www/laravel-s-test/task.php(15): PDO->__construct('mysql:dbname=te...', 'root', 'xy123456')
#1 {main}
  thrown in /Users/dave/Documents/docker/www/laravel-s-test/task.php on line 15

Fatal error: Uncaught PDOException: PDO::__construct(): MySQL server has gone away in /Users/dave/Documents/docker/www/laravel-s-test/task.php:15
Stack trace:
#0 /Users/dave/Documents/docker/www/laravel-s-test/task.php(15): PDO->__construct('mysql:dbname=te...', 'root', 'xy123456')
#1 {main}

Next PDOException: SQLSTATE[HY000] [2006] MySQL server has gone away in /Users/dave/Documents/docker/www/laravel-s-test/task.php:15
Stack trace:
#0 /Users/dave/Documents/docker/www/laravel-s-test/task.php(15): PDO->__construct('mysql:dbname=te...', 'root', 'xy123456')
#1 {main}
  thrown in /Users/dave/Documents/docker/www/laravel-s-test/task.php on line 15
[2018-10-22 11:33:55 ^42927.1]  ERROR   zm_deactivate_swoole (ERROR 503): Fatal error: Uncaught PDOException: PDO::__construct(): MySQL server has gone away in /Users/dave/Documents/docker/www/laravel-s-test/task.php:15
Stack trace:
#0 /Users/dave/Documents/docker/www/laravel-s-test/task.php(15): PDO->__construct('mysql:dbname=te...', 'root', 'xy123456')
#1 {main}

Next PDOException: SQLSTATE[HY000] [2006] MySQL server has gone away in /Users/dave/Documents/docker/www/laravel-s-test/task.php:15
Stack trace:
#0 /Users/dave/Documents/docker/www/la
[2018-10-22 11:33:55 $42926.0]  WARNING swManager_check_exit_status: worker#1 abnormal exit, status=255, signal=0
hhxsv5 commented 5 years ago

@twose

<?php
$http = new swoole_http_server('127.0.0.1', 5200);
$http->set([
    'daemonize'       => false,
    'worker_num'      => 1,
    'task_worker_num' => 1,
]);
$http->on('Request', function (swoole_http_request $request, swoole_http_response $response) use ($http) {
    $taskId = $http->task('run');
    $response->end('Hello LaravelS #' . $taskId);
});
$http->on('Task', function (swoole_http_server $server, $taskId, $srcWorkerId, $data) {
    go(function () {
        \Swoole\Runtime::enableCoroutine(); #注释掉这行就正常
        $pdo = new PDO('mysql:dbname=test;host=127.0.0.1', 'root', 'xy123456');
        $sql = sprintf('insert into test(name,created_at,updated_at) values("%s","%s","%s")', uniqid(),
            date('Y-m-d H:i:s'), date('Y-m-d H:i:s'));
        $pdo->exec($sql);
        var_dump($pdo->lastInsertId());
    });
});
$http->on('Finish', function (swoole_http_server $server, $taskId, $data) {

});
$http->start();
→ php task.php
PHP Warning:  Unknown: onTask handler error. in Unknown on line 0

Warning: Unknown: onTask handler error. in Unknown on line 0
PHP Fatal error:  Uncaught PDOException: PDO::__construct(): MySQL server has gone away in /Users/dave/Documents/docker/www/laravel-s-test/task.php:15
Stack trace:
#0 /Users/dave/Documents/docker/www/laravel-s-test/task.php(15): PDO->__construct('mysql:dbname=te...', 'root', 'xy123456')
#1 {main}

Next PDOException: SQLSTATE[HY000] [2006] MySQL server has gone away in /Users/dave/Documents/docker/www/laravel-s-test/task.php:15
Stack trace:
#0 /Users/dave/Documents/docker/www/laravel-s-test/task.php(15): PDO->__construct('mysql:dbname=te...', 'root', 'xy123456')
#1 {main}
  thrown in /Users/dave/Documents/docker/www/laravel-s-test/task.php on line 15

Fatal error: Uncaught PDOException: PDO::__construct(): MySQL server has gone away in /Users/dave/Documents/docker/www/laravel-s-test/task.php:15
Stack trace:
#0 /Users/dave/Documents/docker/www/laravel-s-test/task.php(15): PDO->__construct('mysql:dbname=te...', 'root', 'xy123456')
#1 {main}

Next PDOException: SQLSTATE[HY000] [2006] MySQL server has gone away in /Users/dave/Documents/docker/www/laravel-s-test/task.php:15
Stack trace:
#0 /Users/dave/Documents/docker/www/laravel-s-test/task.php(15): PDO->__construct('mysql:dbname=te...', 'root', 'xy123456')
#1 {main}
  thrown in /Users/dave/Documents/docker/www/laravel-s-test/task.php on line 15
[2018-10-22 11:33:55 ^42927.1]  ERROR   zm_deactivate_swoole (ERROR 503): Fatal error: Uncaught PDOException: PDO::__construct(): MySQL server has gone away in /Users/dave/Documents/docker/www/laravel-s-test/task.php:15
Stack trace:
#0 /Users/dave/Documents/docker/www/laravel-s-test/task.php(15): PDO->__construct('mysql:dbname=te...', 'root', 'xy123456')
#1 {main}

Next PDOException: SQLSTATE[HY000] [2006] MySQL server has gone away in /Users/dave/Documents/docker/www/laravel-s-test/task.php:15
Stack trace:
#0 /Users/dave/Documents/docker/www/la
[2018-10-22 11:33:55 $42926.0]  WARNING swManager_check_exit_status: worker#1 abnormal exit, status=255, signal=0
twose commented 5 years ago

确认是PHP71的PDO的问题, PHP72无此问题, 待追踪

twose commented 5 years ago

你的MySQL版本是?

hhxsv5 commented 5 years ago

github还没恢复...

hhxsv5 commented 5 years ago

@twose 5.7.23 5.7.21 两个版本都试过。

hhxsv5 commented 5 years ago

@twose 好的,需要新开个issue吗?