我最近使用Django
为"科学计算引擎"编程我的网络界面。
我将"计算引擎"作为Python模块包装,并在Django框架内称为。
"发动机"的compute()
功能需要几分钟才能运行(我使用ajax
触发它(,同时,我让前端每0.5秒拨打额外的ajax
来更新CPU和内存状态到前端。但是我发现服务器在compute()
完成之前没有响应额外的ajax
调用。
搜索后,我想我可能会使用asynchronous
或multithreading
所以我像下面一样在views.py
中制作功能。
def submit(request):
#some prepare
........
# call the engine
t = Thread(target = compute)
t.start()
return HttpResponse("started")
但是,直到compute()
完成之前,系统仍然不会响应我的额外ajax
调用("发动机"仅使用CPU的20%左右,因此剩下大量的计算功率(。
我是后端编程的新手,我不确定Django
或后端服务器处理请求在内部如何。非常感谢您,如果有人可以给我一些有关如何处理这种情况的暗示。
我最终使用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
不是一个很好且安全的练习。该解决方案很容易实现,但是我将尝试通过使用 Celery
或 django-channels
将后端转换为 worker mode
。
从这样的视图启动线程绝不是一个好主意。
解决此问题的最常见方法是将工作委派给单独的工人/过程。除Django外,您还有另一个python过程正在寻找工作。
您可以保持简单,并使Django查看商店有关需要在磁盘或数据库中以某种格式完成的工作的信息(这是工作队列(。然后,工作过程将每秒钟一次进行一次循环检查是否可用工作。增加工人/流程的数量,以增加更多的计算能力(当然受硬件的限制(
创建工作请求的HTTP请求可以返回job_id
用户可以查询以获取工作状态。工作正在进行/正在进行/完成吗?然后,也许用户也可以获取作业的结果,甚至可以获取诸如持续时间和日志之类的元数据?
也有框架可以解决此类问题,例如芹菜和Django通道。芹菜可能更容易开始,但是对于您想做的事情可能会过大。
使用这样的工人的优点是,您可以在前面有一个非常轻巧的REST API,并且可以随着需求的增加而跨多个服务器进行扩展。