Django在执行计算密集型任务时没有响应Ajax调用

时间:2017-04-30 11:50:41

标签: python ajax django asynchronous backend

我最近使用Django为我的“科学计算引擎”编程我的网络界面。

我将“计算引擎”包装为python模块并在Django Framework中调用它。

“引擎”的compute()功能需要几分钟才能运行(我使用ajax来触发它),同时,我让前端额外增加{{1}每隔0.5秒调用一次,将CPU和内存状态更新到前端。但我发现服务器在ajax完成之前没有响应额外的ajax来电。

搜索后,我想我可能会使用compute()asynchronous

的想法

所以我在multithreading中创建了如下所示的功能。

views.py

但是系统仍然没有响应我的额外def submit(request): #some prepare ........ # call the engine t = Thread(target = compute) t.start() return HttpResponse("started") 调用,直到ajax完成(“引擎”仅使用了大约20%的CPU,因此还有足够的计算能力)。

我是后端编程的新手,我不确定compute()或后端服务器如何在内部处理请求。 非常感谢,如果有人能给我一些关于如何处理这种情况的提示。

2 个答案:

答案 0 :(得分:1)

从这样的视图中启动线程永远不是一个好主意。

解决此问题的最常见方法是将工作委托给单独的工作人员/流程。除了django之外,你还有另一个寻找工作的python进程。

您可以保持简单,并使Django视图存储有关需要以某种格式在磁盘或数据库中完成的工作的信息(这将是工作队列)。然后,工作进程将在循环中运行,每N秒检查一次可用的工作。增加工作人员/进程数量以增加更多计算能力(当然受硬件限制)

创建工作请求的http请求可以返回用户可以查询的job_id以获取作业的状态。工作正在等待/正在进行/已完成?那么也许用户也可以获取作业的结果甚至是元数据,例如持续时间和日志?

还有一些框架可以解决像Celery和django-channels这样的问题。芹菜可能更容易入手,但对于你想要做的事情可能有点过头了。

使用这样的工作人员的优势在于,您可以在前面拥有一个非常轻量级的REST api,并且随着需求的增加,您可以扩展工作人员的数量,可能跨多个服务器。

答案 1 :(得分:1)

我终于通过使用python subprocess

解决了这个问题

我将“计算”代码放在一个单独的文件中,并使用Popen来调用它。

from subprocess import Popen def submit(request): #some prepare ........ # call the engine p = Popen(["python", "compute.py", <arguments>]) return HttpResponse("started")

然而,正如所建议的,subprocess不是一个非常好的安全做法。此解决方案很容易实现,但我会尝试使用worker modeCelery将后端转换为django-channels,作为@Grimmy建议。