Nginx + PHP:在被取消的请求时停止进程 [英] Nginx + PHP: stop process at canceled request

查看:136
本文介绍了Nginx + PHP:在被取消的请求时停止进程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有Nginx 1.4.4和PHP 5.5.6.我正在进行长时间轮询的请求.问题是,如果我取消了通过Ajax发送的HTTP请求,则请求仍在处理中(它们不会停止).我在文件末尾使用PHP mail()函数对其进行了测试,但是邮件仍在继续,文件并没有停止.)

I have Nginx 1.4.4 and PHP 5.5.6. I'm making long-polling requests. Problem is, that if I cancel the HTTP request sent via Ajax, requests are still processing (they don't stop). I tested it with the PHP mail() function at end of file, and mail is still coming the file didn't stop).

我很担心,因为我认为由于未关闭请求的负载很大,它可能导致服务器崩溃.是的,我尝试了ignore_user_abort(false);,但没有任何更改.我有可能应该在Nginx中进行一些更改吗?

I'm worried, because I think that it might cause server crash because of the high load of unclosed requests. Yes, I tried ignore_user_abort(false); but with no changes. Is possible that I should change something in Nginx?

  location ~ \.php$ {    
    try_files $uri =404;
    include fastcgi_params;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;  
  }

推荐答案

坏消息是,您几乎肯定无法解决您想解决的问题.客户端在收到请求之前关闭连接时发送的FastCGI信号为 FCGI_ABORT_REQUEST

The bad news is you are almost certainly not going to be able to solve you problem how you want to solve it. The FastCGI signal sent when a client closes a connection before receiving a request is FCGI_ABORT_REQUEST

当HTTP客户端关闭其Web服务器时,它会终止FastCGI请求 代表FastCGI请求运行时的传输连接 那位客户.这种情况似乎不太可能发生.大多数FastCGI请求 Web服务器提供输出,响应时间短 如果客户端运行缓慢,则进行缓冲.但是FastCGI应用程序可能是 延迟与另一个系统通信或执行服务器 推.

A Web server aborts a FastCGI request when an HTTP client closes its transport connection while the FastCGI request is running on behalf of that client. The situation may seem unlikely; most FastCGI requests will have short response times, with the Web server providing output buffering if the client is slow. But the FastCGI application may be delayed communicating with another system, or performing a server push.

不幸的是,它看上去既没有原始的 fast-cgi实现 PHP-FPM 支持FCGI_ABORT_REQUEST信号,因此不能被中断.

Unfortunately it looks like neither the original fast-cgi implementation nor PHP-FPM support the FCGI_ABORT_REQUEST signal, and so can't be interrupted.

好消息是,有更好的方法来解决此问题.基本上,您永远都不会有需要很长时间才能处理的请求.相反,如果请求需要很长时间才能处理,您应该:

The good news is there are better ways to solve this problem. Basically you should never have requests that take a long time to process. Instead if a request needs a long time to process you should:

  • 将其推送到需要处理的任务队列中.
  • 将任务ID"返回给客户端.
  • 让客户端定期轮询以查看该任务"是否已完成,并在完成时显示结果.

除了这3项基本内容外,如果您担心在客户端不再对请求结果感兴趣时浪费系统资源,则应该添加:

In addition to those 3 basic things - if you're concerned about wasting system resources when a client is no longer interested in the results of a request you should add:

  • 将任务分解为小部分工作,如果客户仍在请求结果,则只能将任务从一个工作状态"转移到下一个工作状态.

您不必说您的长期任务是什么-让我们假装是要从另一台服务器下载大型图像文件,操纵该图像,然后将其存储在S3中.因此,此任务的状态将类似于:

You don't say what your long running task is - let's pretend that it's to download a large image file from another server, manipulate that image, and then store it in S3. So the states for this task would be something like:

TASK_STATE_QUEUED
TASK_STATE_DOWNLOADING //Moves to next state when finished download
TASK_STATE_DOWNLOADED
TASK_STATE_PROCESSING  //Moves to next state when processing finished
TASK_STATE_PROCESSED
TASK_STATE_UPLOADING_TO_S3 //Moves to next state when uploaded
TASK_STATE_FINISHED

因此,当客户端发送初始请求时,它会获取一个taskID,然后在查询该任务的状态时:

So when the client sends the initial request, it gets back a taskID and then when it queries the state of that task, either:

  • 服务器报告任务仍在进行中

  • 如果它处于以下状态之一,则客户端请求会将其更改为下一个状态.

TASK_STATE_QUEUED => TASK_STATE_DOWNLOADING
TASK_STATE_DOWNLOADED => TASK_STATE_PROCESSING
TASK_STATE_PROCESSED => TASK_STATE_UPLOADING_TO_S3

因此仅继续处理客户感兴趣的请求.

So only requests that the client is interested in continue to be processed.

顺便说一句,我强烈建议您使用设计成可表现良好的东西作为队列来保存任务队列(例如 Redis Gearman ),而不仅仅是使用MySQL或任何数据库.基本上,SQL并不能很好地充当队列,您最好从一开始就使用适当的技术,而不要使用错误的技术来启动,然后在数据库变为紧急状态时必须将其替换出来.尝试执行数百个插入操作时超载,每秒更新一次即可管理任务.

btw I'd strongly recommend using something that is designed to work performantly as a Queue for holding the queue of tasks (e.g. Rabbitmq, Redis or Gearman ) rather than just using MySQL or any database. Basically, SQL just isn't that great at acting as a queue and you would be better using the appropriate technology from the start, rather than using the wrong tech to start, and then having to swap it out in an emergency when your database becomes overloaded when it's trying to do hundreds of inserts, updates per second just to manage the tasks.

作为附带的好处,通过将长时间运行的流程分解成多个任务,变得非常容易:

As a side benefit, by breaking long running process up into tasks, it becomes really easy to:

  1. 查看处理时间在哪里.
  2. 查看并检测处理时间的波动(例如,如果CPUS利用率达到100%,那么图像调整大小将突然花费更长的时间).
  3. 在缓慢的步骤上投入更多的资源.
  4. 您可以将状态更新消息发送给客户端,以便他们可以看到任务的进度,这提供了更好的UX,而不是仅仅坐在那里什么也不做".

这篇关于Nginx + PHP:在被取消的请求时停止进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆