使用Django和FastCGI管理长时间运行的过程

在这里插入图片描述

  1. 问题背景:

    • 有一个Django+FastCGI的应用程序,需要修改以执行长时间的计算(可能长达半小时或更久)。
    • 需要在后台运行计算,并返回“您的作业已启动”类型的响应。
    • 在进程运行期间,进一步访问该URL应返回“您的作业仍在运行”,直到作业完成,此时应返回作业结果。
    • 以后任何对该URL的访问都应返回缓存的结果。
    • 对Django不太熟悉,不知道是否有内置的方法来实现想要的功能。
    • 尝试通过subprocess.Popen()启动进程,但除了在进程表中留下一个失效的条目之外,它工作正常。
    • 需要一个干净的解决方案,可以在进程完成后删除临时文件和进程的任何痕迹。
    • 也尝试了fork()和线程,但还没有想出可行的解决方案。
    • 想知道对于看似很常见的用例,是否存在规范的解决方案。
  2. 解决方案:

    • 可以使用两种可能的解决方案:

      • 调度长时任务到长时任务管理程序(可能是上面提到的Django-Queue-Service)。
      • 将结果永久保存,无论是文件还是数据库。
    • preferred to use temporary files and to remember their locaiton in the session data. It cannot be made more simple:

    • 代码示例:

      import sys
      from time import sleep
      

i = 0
while i < 1000:
print(‘myjob:’, i)
i = i+1
sleep(0.1)
sys.stdout.flush()

     ```python
from tempfile import mkstemp
from os import fdopen,unlink,kill
from subprocess import Popen
import signal

def startjob(request):
     """Start a new long running process unless already started."""
     if not request.session.has_key('job'):
          # create a temporary file to save the resuls
          outfd,outname=mkstemp()
          request.session['jobfile']=outname
          outfile=fdopen(outfd,'a+')
          proc=Popen("python myjob.py",shell=True,stdout=outfile)
          # remember pid to terminate the job later
          request.session['job']=proc.pid
     return HttpResponse('A <a href="/showjob/">new job</a> has started.')

def showjob(request):
     """Show the last result of the running job."""
     if not request.session.has_key('job'):
          return HttpResponse('Not running a job.'+\
               '<a href="/startjob/">Start a new one?</a>')
     else:
          filename=request.session['jobfile']
          results=open(filename)
          lines=results.readlines()
          try:
               return HttpResponse(lines[-1]+\
                         '<p><a href="/rmjob/">Terminate?</a>')
          except:
               return HttpResponse('No results yet.'+\
                         '<p><a href="/rmjob/">Terminate?</a>')
     return response

def rmjob(request):
     """Terminate the runining job."""
     if request.session.has_key('job'):
          job=request.session['job']
          filename=request.session['jobfile']
          try:
               kill(job,signal.SIGKILL) # unix only
               unlink(filename)
          except OSError, e:
               pass # probably the job has finished already
          del request.session['job']
          del request.session['jobfile']
     return HttpResponseRedirect('/startjob/') # start a new one
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值