异步执行Web应用程序的任务

时间:2009-11-17 12:03:57

标签: ajax asynchronous job-queue

我正在开发的Web应用程序需要执行在http请求/响应周期中执行太长而无法执行的任务。通常,用户将执行请求,服务器将接受此请求,并且除其他外,运行一些脚本以生成数据(例如,使用povray渲染图像)。

当然,这些任务可能需要很长时间,因此在将响应发送到客户端之前,服务器不应挂起以使脚本完成执行。因此,我需要执行脚本async的执行,并给客户端“资源在这里,但没有准备好”,并可能告诉它一个ajax端点进行轮询,因此它可以在准备好时检索并显示资源。

现在,我的问题与设计无关(尽管我非常喜欢这方面的任何提示)。我的问题是:解决这个问题的系统是否已经存在,所以我不重新发明方形轮?如果必须的话,我会使用进程队列管理器来提交任务并放置一个HTTP端点来发送状态,例如“pending”,“aborted”,“completed”到ajax客户端,但是如果已经类似了专门为这项任务而存在,我会非常喜欢它。

我在python + django工作。

编辑:请注意,此处的主要问题不是服务器和客户端必须如何协商和交换有关任务状态的信息。

问题是服务器如何处理很长任务的提交和入队。换句话说,我需要一个比我的服务器在LSF上提交脚本更好的系统。并不是说它不起作用,但我觉得它有点太多了......

编辑2 :我添加了赏金以查看是否可以获得其他答案。我检查了pyprocessing,但我无法执行提交作业并在稍后阶段重新连接到队列。

7 个答案:

答案 0 :(得分:4)

你应该避免在这里重新发明轮子。

结帐gearman。它有很多语言的库(包括python),并且相当受欢迎。不确定是否有任何开箱即用的方法可以轻松地将django连接到gearman和ajax调用,但是自己做这部分并不是很复杂。

基本思想是你运行gearman作业服务器(或多个作业服务器),让你的web请求排队一个工作(比如'resize_photo')和一些参数(比如'{photo_id:1234}')。您将此作为后台任务排队。你得到一个回头。然后,您的ajax请求将轮询该句柄值,直到它被标记为完成。

然后你有一个工作者(或者可能很多)是一个单独的python进程连接到这个作业服务器并为“resize_photo”作业注册自己,做了工作,然后将其标记为完成。

我还发现这个blog post能够很好地总结它的用法。

答案 1 :(得分:1)

您可以尝试两种方法:

  • 调用网络服务器 n 间隔并通知作业ID;服务器进程并返回有关该任务当前执行的一些信息
  • 要实现一个长时间运行的页面,每隔 n 间隔发送数据;对于客户端,HTTP请求将“始终”为"loading",并且每次收到新数据时都需要收集新信息。

关于第二个选项,您可以通过阅读Comet了解更多信息;使用ASP.NET,您可以通过实现System.Web.IHttpAsyncHandler接口来做类似的事情。

答案 2 :(得分:1)

我不知道有哪个系统可以做到这一点,但实现自己的系统会相当容易:

  • 使用jobid,jobparameters,jobresult创建数据库表
    • jobresult是一个字符串,用于保存结果
    • jobparameters是输入参数的pickle列表
  • 当服务器开始处理某个作业时,它会在表中创建一个新行,然后生成一个新进程来处理该行,并将该进程传递给jobid
  • 任务处理程序进程在完成后更新表中的jobresult
  • 一个网页(xmlrpc或你正在使用的任何东西)包含一个方法'getResult(jobid)',它将检查表的jobresult
    • 如果找到结果,则返回结果,并从表中删除该行
    • 否则返回空列表,或者无,或者您的首选返回值表示作业尚未完成

有一些边缘情况可以照顾,所以现有的框架显然会更好,就像你说的那样。

答案 3 :(得分:1)

首先你需要一些单独的“工作”服务,它将在通电时单独启动,并通过一些本地IPC(如UNIX-socket(快速)或数据库(简单))与http-request处理程序进行通信。

在处理请求期间,cgi从工作人员状态或其他数据询问并重播给客户。

答案 4 :(得分:0)

您可以通过回复202 HTTP代码来表示资源正在“处理”:客户端将不得不稍后重试以获取已完成的资源。根据具体情况,您可能必须发出“请求ID”才能将请求与响应匹配。

或者,您可以查看现有的COMET库,这些库可能会“开箱即用”地满足您的需求。我不确定是否有任何匹配你当前的Django设计。

答案 5 :(得分:0)

对于您正在使用的python / django解决方案,可能不是一个很好的答案,但我们使用Microsoft Message Queue来做这样的事情。它基本上就像这样运行

  1. 网站在某处以“处理”状态更新数据库行
  2. 网站向MSMQ发送消息(这是一个非阻塞调用,因此它会立即将控制权返回给网站)
  3. Windows服务(可能是任何程序)正在“观察”MSMQ并获取消息
  4. Windows服务以“已完成”状态更新数据库行。
  5. 无论如何,这是它的要点。它对我们来说非常可靠,并且非常直接地进行扩展和管理。

    -al

答案 6 :(得分:0)

python和django的另一个好选择是Celery

如果您认为Celery太重而无法满足您的需求,那么您可能需要查看简单的分布式taskqueue