2009-11-17 82 views
3

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

当然,这些任务可能需要很长时间,因此在向客户端发送响应之前,服务器不应挂起脚本以完成执行。因此,我需要执行异步脚本的执行,并为客户端提供“资源在这里,但没有准备好”,并且可能会告诉它一个ajax端点轮询,以便它可以在准备就绪时检索和显示资源。

现在,我的问题与设计无关(尽管我也非常喜欢这方面的任何提示)。我的问题是:解决这个问题的系统是否已经存在,所以我不重新发明方形轮?如果必须的话,我会使用一个进程队列管理器来提交任务,并把一个HTTP端点发送给ajax客户端,比如“挂起”,“中止”,“完成”专门为这项任务而存在,我主要会喜欢它。

我正在使用python + django。

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

问题是服务器如何处理提交和排队很长的任务。换句话说,我需要一个比我的服务器在LSF上提交脚本更好的系统。不,这是行不通的,但我认为这是一个有点太多...

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

回答

4

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

结账gearman。它有许多语言的库(包括python),并且非常流行。不知道是否有人可以使用任何方法轻松地将django连接到gearman和ajax调用,但是自己做这个部分不应该很复杂。

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

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

我也发现了这个blog post,做了很好的工作,总结它的用法。

+0

看起来像它正是我需要的。谢谢 – 2009-12-02 03:08:42

+0

不错!看起来像是将来使用的有用框架。凉! – 2009-12-03 02:54:07

1

你可以设法在历时技术途径:

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

关于第二种方法,您可以通过阅读Comet了解更多信息;使用ASP.NET,您可以通过实现System.Web.IHttpAsyncHandler界面来做类似的事情。

+0

不是我的问题。我的问题是从服务器应用程序提交服务器端的东西。换句话说 服务器<-1-> Web界面<-2->客户 阿贾克斯解决了我2,而不是1 – 2009-11-17 12:09:58

+0

不,我炼的问题,只是几秒钟 – 2009-11-17 12:15:32

0

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

或者,你可以看看现有的COMET库,它可能会更“满载”地满足你的需求。我不确定是否有任何匹配你当前的Django设计。

1

我不知道,做这一个系统的,但它是非常容易实现自己的系统:

  • 创建数据库表作业ID,jobparameters,jobresult
    • jobresult是将保存结果的泡菜
    • jobparameters一个字符串的输入参数的腌列表
  • 当服务器开始于一个岗位上工作,它在表中创建一个新的行,spwans一个新的进程来处理,通过该进程的作业ID
  • 任务处理过程更新在表中jobresult当它已经完成
  • 一网页(XML-RPC或者任何你正在使用)包含方法“的getResult(作业ID)”,将检查表的jobresult
    • 如果它发现一个结果,它返回的结果,并从表中删除该行
    • 否则返回一个空列表,或无,或您首选的返回值,以表示该工作尚未完成

有几个边缘情况需要照顾,所以现有的框架显然会更好,就像你说的那样。

1

首先你需要一些独立的“工作人员”服务,该服务将分别在上电时通过一些当地的IPC像UNIX插座(快)或数据库(简单)开始,并与HTTP请求处理程序进行通信。

在处理请求的CGI从工作者状态或其他数据要求和重放客户。

0

可能并不适合你正在使用的蟒蛇/ Django的解决方案有很大的答案,但是我们使用微软消息队列的事情就是这样的。它基本上运行这样

  1. 网站某处更新数据库行用“处理”状态
  2. 网站将消息发送到MSMQ(这是一个非阻塞调用,因此控制权交还给该网站马上)
  3. Windows服务(可以是任何程序)正在“观察”MSMQ并获取消息
  4. Windows服务以“已完成”状态更新数据库行。

无论如何这就是它的要义。对我们来说这是相当可靠的,并且非常简单地进行扩展和管理。

-al

0

Python和Django的另一个很好的选择是Celery

如果您认为芹菜太重,您的需要,那么你可能想看看简单的分布taskqueue