swoole / rfc

Swoole 提案
116 stars 3 forks source link

RFC-1007 希望 Swoole\Http\Response 可以在别的进程中构造并使用 #15

Closed breath-co2 closed 6 years ago

breath-co2 commented 6 years ago

问题描述

当一个 http 的 onRequest 请求时,系统会自动构造出一个 $request, $response 对象,通过 $response 可以给客户端发送消息,但是仅仅局限在当前进程里,如果 onRequest() 请求后给一个 task 投递(或别的进程)处理后,必须要返回到当前 worker 才可以使用 $response 进行回html信息,在异步方面处理起来就比较麻烦:你得把 $response 放在一个临时变量里,然后再监听一个 onFinish() 并且在需要 task进程把回的消息通过 onfinish 传回来,效率低下且不好维护代码。

建议

$response 提供 hold() 方法可以暂存对象,然后在别的进程里可以通过 Swoole\Http\Response::instance($fd) 获取,或还有更简便的,比如 $server->getResponse($fd),获取到 $response 对象就可以正常操作了。

伪代码实现

<?php
$http = new Swoole\Http\Server("127.0.0.1", 9501);
$http->set(array('task_worker_num' => 2));
$http->on("start", function ($server) {
    echo "Swoole http server is started at http://127.0.0.1:9501\n";
});

$http->on("request", function ($request, $response) {
    $response->hold();           // 标记为暂存,使得在 onRequest() 结束后不自动执行 $respons->end('') 逻辑
    // ..... 一些逻辑处理
    $server->task($response->fd);         // 投递给task处理
});

$http->on('task', function ($server, $task_id, $reactor_id, $data) 
{
    echo "New AsyncTask[id=$task_id]\n";
    $fd = $data;
    $response = $server->getResponse($fd);       // 在 task 中通过 fd 获取,只有被 hold() 了的才可以获取到
    if ($response !== false)
    {
        $html = '...';
        $response->end($html);              // 在 task 里直接把内容输出给浏览器
    }
});

$http->start();
matyhtf commented 6 years ago

考虑了一下,可以通过新增 detachcreate 来实现。

分离

使用后__destruct不再自动end

$response->detach(); 

构建

$response = Swoole\Http\Response::create($fd);

构造一个Response对象。

matyhtf commented 6 years ago

https://github.com/swoole/swoole-src/commit/3d225e589e3123ca37673d1e89e7d93f271376de