【问题标题】:Gearman processing in parallel and give output intermedeateGearman 并行处理并提供中间输出
【发布时间】:2015-08-18 14:31:35
【问题描述】:

我正在使用 Gearman 和 Slim PHP 创建 restful API,其中:

用户将调用一个 RESTful API 并发送一个文件 url。这将:

  1. 下载文件 - 并向用户发送唯一的文件 ID 作为 http 响应
  2. 发送响应后,我想开始处理文件
  3. 用户可以通过GET www.example.com/api/status API调用查看进程状态

我已使用 gearman 为文件下载部分执行正常操作,但只有在处理完成后才会发送状态响应。另外,如何获取每个客户端进程的状态? 我需要更多帮助来了解如何准确地构建相同的结构,以及一些关于排队处理的细节,因为我是 gearman 新手。

【问题讨论】:

    标签: php rest slim task-queue gearman


    【解决方案1】:

    您需要使用jobstatusdoBackground()。 首先,您需要初始化传输。这是通过将任务发送到后台并向用户发送作业句柄来完成的。您通过 yourserver.com/api/file-transfer 调用它,并且必须发送一个设置了 fileurl 的 POST 请求。答案是一个 json 对象。

    <?php
    // use composer for slim
    require_once "vendor/autoload.php"; 
    $app = new \Slim\Slim();
    
    // init file transfer
    $app->post('/file-transfer', function () use ($app) {
        $resp = array();
        try {
            // get file url
            $fileurl = $app->request->post('fileurl');
            $data = json_encode(array("fileurl"=>$fileurl);
    
            // send to gearman
            $client = new GearmanClient();
            $client->addServer();
    
            // store the gearman handle and send the task to the background
            $jobHandle = $client->doBackground("fileUpload", $data);
    
            if ($client->returnCode() != GEARMAN_SUCCESS) throw new Exception("Could not add the job to the queue.", 1);
    
            $resp["msg"] = "File upload queued";
            $resp["handle"] = $jobHandle;
        } catch(Exception $e) {
            // some error handling
            $resp["msg"] = "There occured a strange error.";
            $resp["error"] = true;
        } finally {
            $response = $app->response();
            $response['Content-Type'] = 'application/json';
            $response->status(200);
            $response->body(json_encode($resp));    
        }
    });
    ?>
    

    在第二步中,用户需要使用作业句柄(他从第一次调用中收到)查询服务器:

    $app->post('/file-status', function () use ($app) {
        $jobHandle = $app->request->params('handle');
        $resp = array();
        try {
            // ask for job status
            $client = new GearmanClient();
            $client->addServer();
            $stat = $client->jobStatus($jobHandle);
            if (!$stat[0]) { // it is done
                $resp["msg"]    = "Transfer completed.";
            } else {
                $resp["msg"]    = "Transfer in progress.";
                $w = (float)$stat[2]; // calculate the percentage
                $g = (float)$stat[3];
                $p = ($g>0)?$w/g*100:0;
                $resp["percentage"] = $p;
            }
        } catch(Exception $e) {
                // some error handling
                $resp["msg"] = "There occured a strange error.";
                $resp["error"] = true;
        } finally {
            $response = $app->response();
            $response['Content-Type'] = 'application/json';
            $response->status(200);
            $response->body(json_encode($resp));    
        }
    });
    

    在第二个请求中,您有来自 $client->jobStatus() 的 $stats 数组。 $stats[0] 告诉您该作业是否为 gearman 服务器所知。第二个元素检查它是否正在运行,并使用三和四 (2/3) 来计算传输的百分比(您需要自己设置这些值!)。

    【讨论】:

    • 是的,一些代码真的很有帮助。我无法发送响应,然后在它之后继续处理
    • 我明白了,但是,我想在文件上传完成后向用户回显响应。然后启动一个我想向用户显示状态的新进程(处理上传的文件)。状态不应该是 fileupload API
    • 不幸的是,Gearman 中的 callbacks don't work on background jobs。因此,一个可能的解决方案是使用jquery ajax 并每隔五到十秒轮询一次服务器,直到处理完成。
    猜你喜欢
    • 2020-11-14
    • 1970-01-01
    • 2010-10-07
    • 2019-05-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-07
    • 2016-01-23
    • 1970-01-01
    相关资源
    最近更新 更多