CodeIgniter RESTful,异步/后台进程

Posted

技术标签:

【中文标题】CodeIgniter RESTful,异步/后台进程【英文标题】:CodeIgniter RESTful, async / background process 【发布时间】:2012-12-03 11:53:02 【问题描述】:

我正在使用 codeIgniter RESTful API (https://github.com/philsturgeon/codeigniter-restserver) 将信息(json 格式)返回到我的 android/iphone 应用程序。

有一个操作,我发送一些值,如果一切正常,我返回 200 代码作为响应。

现在,我想以相同的方法添加一个新操作:使用 APNS(Apple Push Notificacion Service)和 GCM(Google Cloud Messaging)发送此修改的通知。

当我必须发送不超过 3-5 个通知时效果很好,问题是 APNS,因为我必须一一发送此消息并且需要很长时间,所以我的应用程序收到超时异常(所有通知已发送,但用户收到错误连接...)

我可以发送 200 代码响应,然后继续发送此通知吗? (像这样……)

function my_update_method_post()
   //....GET my POST values
   update($data);
   $this->response(array('result'=>1),200));


   //Send Notifications
   ....

提前谢谢...

【问题讨论】:

【参考方案1】:

我找到了一个非常适合我的解决方案,因为我不期望任何结果值。如果无法发送通知...我将其记录在我的数据库中。

这是我用来发送“异步”请求的函数(是的,这不是异步请求,但它可以按照我的要求工作)

function curl_post_async($url, $params)

    $post_string = http_build_query($params);
    $parts=parse_url($url);

    $fp = fsockopen($parts['host'],
        isset($parts['port'])?$parts['port']:80,
        $errno, $errstr, 30);

    if(!$fp)
    
        //Perform whatever logging you want to have happen b/c this call failed!    
    
    $out = "POST ".$parts['path']." HTTP/1.1\r\n";
    $out.= "Host: ".$parts['host']."\r\n";
    $out.= "Content-Type: application/x-www-form-urlencoded\r\n";
    $out.= "Content-Length: ".strlen($post_string)."\r\n";
    $out.= "Connection: Close\r\n\r\n";
    if (isset($post_string)) $out.= $post_string;

    fwrite($fp, $out);
    fclose($fp);

【讨论】:

我其实不喜欢这种方法,因为当客户端告诉连接立即关闭时,服务器可能会停止处理。此外,客户端没有机会接收来自服务器的响应。看看我的解决方案,保证服务器持续运行。 也就是说,我确实意识到立即断开连接(通过客户端请求标头)可以满足您的需求。【参考方案2】:

是的,这是可能的。

您应该查看php exec() 和this 链接。您应该在控制器中设置一个函数,以便从命令行调用。然后,您将传入要使用的 GCM/APNS 数据数组。

此解决方案并不理想,因为您无法告诉客户端所有消息都已成功发送。您将返回 200 表示请求已收到,仅此而已。

【讨论】:

您使用的是共享主机吗? 那是你的问题。共享主机可能会限制执行,等等。如果他们可以为您启用它,也许就像他们一样。【参考方案3】:

由于 PHP 本身不支持线程或异步函数调用,您将不得不使用一种 hacky 解决方案。 在这里看看我的问题:PHP file_get_contents() follow Content-length header

解决方案是发送Connection: CloseContent-Length 标头,然后让客户端知道这些标头(参见上面的链接)。例如,在 curl 的情况下,一旦达到 Content-Length,连接就会关闭,但您的 PHP 脚本仍然“在后台”运行,因此您可以开始耗时的操作。

亲切的问候,

斯蒂芬

附:如果脚本需要很长时间才能执行,请确保 PHP 最大执行时间不会妨碍您

【讨论】:

你认为我可以用下一个信息做到这一点吗?我现在不能尝试 - Link1 wishmesh.com/2009/08/… Link2 blog.markturansky.com/archives/205 (【参考方案4】:

看看this article。我喜欢这个解决方案不仅仅是让客户端告诉服务器立即挂断;如果您在服务器端构建此解决方案,会有很多好处。

    您知道一旦客户端断开连接,服务器将继续处理 客户端仍然可以收到来自服务器的响应

编辑

我没有意识到 OP 无法访问此处的服务。在这种情况下,我提到的文章没有什么价值。这里的问题是服务器需要很长时间才能响应并挂起客户端。为此,我建议curl_multi_init。这允许您同时发出多个请求。

【讨论】:

嗨@quickshiftin,用这个解决方案,你的意思是我必须把我的代码放在“这是常规请求代码所在的地方......结束常规请求代码运行的地方......”之间删除此行 $out.= "Connection: Close\r\n\r\n"; ??? 嗯,我昨晚似乎没有读到足够的内容。我展示的代码是服务器端代码,但如果您不编写服务器,那么您将无法使用此代码。抱歉,我会编辑答案。

以上是关于CodeIgniter RESTful,异步/后台进程的主要内容,如果未能解决你的问题,请参考以下文章

[CI] 使用CodeIgniter框架搭建RESTful API服务

Codeigniter RESTful API 服务器 - XML 错误?

NodeJs中的异步

在后台运行 Codeigniter URL

如何使用 RESTful Web 服务创建异步通知系统?

java后台接口怎么方便返回restful数据