swoole / swoole-src

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

zm_deactivate_swoole (ERROR 503): Fatal error: swoole_http_response::end(): handle 772240936 exceed 10000000 #977

Closed mysteriouss closed 7 years ago

mysteriouss commented 7 years ago

swoole_http_server是否支持类似用法,issue 618

$http->task( 'taskData',-1, function($serv,$task_id,$data) use (&$response){
    $response->status(200);
    $response->end();
});
matyhtf commented 7 years ago

PHP7吗?

matyhtf commented 7 years ago

去掉 & 引用符号试试。这可能会导致底层引用计数错误。

mysteriouss commented 7 years ago

PHP 5.6.29,去掉引用也是crash,$response什么时候释放呢

PHP Fatal error:  swoole_http_response::end(): handle 859337816 exceed 10000000 in test.php line 20
WARNING swManager_check_exit_status: worker#2 abnormal exit, status=255, signal=0
mysteriouss commented 7 years ago

虽然worker退出了,但是客户端收到了正确的end返回结果

matyhtf commented 7 years ago

本地使用 PHP5.6.9 无法重现你的问题。可以正确处理,是否安装了特殊的扩展,或者代码中有特殊逻辑,使用了某些 引用操作。

mysteriouss commented 7 years ago

task的返回我用的$http->finish($data); 而不是直接return的,不知道是不是因为这

mysteriouss commented 7 years ago

有的时候不报这个错误,但是不能接收到任何请求了

mysteriouss commented 7 years ago

ctrl+c kill -2再重启服务后,然后就出现这个错误提示

mysteriouss commented 7 years ago

改成在onTask里直接return了,同样的情况

补充下复现顺序

  1. 接受请求异步处理,调用了几次到十几次不等,请求卡住不响应,过了几十秒种响应
  2. ctrl+c,重启,报上面错误 exceed 10000000
matyhtf commented 7 years ago

是否使用了消息队列模式,改成unix socket试试。

mysteriouss commented 7 years ago

没有写task_ipc_mode

默认是unix socket吧,我试下定向投递

是要把-1改成task worker ?

mysteriouss commented 7 years ago

server:

$http = new swoole_http_server("0.0.0.0", $swoole_serv_port, SWOOLE_PROCESS);
$http->set([
    'worker_num' => 16,
    'dispatch_mode' => 2,
    'open_tcp_nodelay' => true,
    'task_worker_num' => 4,
    'task_ipc_mode' => 2,
    //'daemonize' => true,
    //'log_file' => '', 
]);

task:

$http->task(
        array(
            Constants::$k_topic => 'share',
            Constants::$k_payload => array('message'=>'','url'=>'https://www.google.com.hk'),
        ), 1, function($serv,$task_id,$data) use($response){

        $response->status(200);
        $response->end(json_encode($data));
    });

onTask:

$http->on('task', function ($serv, $task_id, $from_id, $data) {
      if(array_key_exists(Constants::$k_topic,$data) &&
            array_key_exists(Constants::$k_payload,$data)) {

            $topic = $data[Constants::$k_topic];
            $payload = $data[Constants::$k_payload];

            if($topic === 'share'){
                //sleep(1);
                return $payload;
            }
        }
}

定向投递和unix socket一样,十几次请求后也卡住

matyhtf commented 7 years ago

任务执行太慢,进程会卡住。

mysteriouss commented 7 years ago

的确有几处对$response的引用,是这个造成的吗?在接收到请求后 是这样处理的

request:

$http->on('request', function(swoole_http_request $request, swoole_http_response $response)
{

    $uri = $request->server['request_uri'];
    $method = $request->server['request_method'];
    echo Utils::localtime() ."[PID=" . posix_getpid() . "]\t". "#[{$request->fd}]\t" . $uri . PHP_EOL;

    if($method === 'GET'){
        route_get($uri,$response);
    }elseif($method === 'POST'){
        $raw = json_decode($request->rawContent(),true);

        echo Utils::localtime() ."[PID=" . posix_getpid() . "]\t". "#[{$request->fd}]\t". $method.  PHP_EOL;
        echo Utils::localtime() ."[PID=" . posix_getpid() . "]\t". "#[{$request->fd}]\t". json_encode($raw). PHP_EOL;
        route_post($uri,$response,$raw);
    }
    else{
        $response->status(501);
        $response->end('501');
    }
});

route:

function route_get(&$uri,&$response){}

function route_post(&$uri, &$response, &$raw){

        $http->task(
                array(
                    Constants::$k_topic => 'share',
                    Constants::$k_payload => array('message'=>'','url'=>'https://www.google.com.hk'),
                ), 1, function($serv,$task_id,$data) use($response){

                $response->status(200);
                $response->end(json_encode($data));
            });
}
matyhtf commented 7 years ago

去掉 & 符号。

mysteriouss commented 7 years ago

ok, 传递其它数据也都要去掉吗还是只有response

mysteriouss commented 7 years ago

应该可以了,谢谢!