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: Close
和Content-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服务