使用python的多处理使得响应挂在gunicorn上

时间:2015-03-20 20:13:55

标签: python flask multiprocessing gunicorn

首先,我承认该标题中有几个关键字,但我确实试图以正确的方式捕获问题。这里的问题是我似乎无法使用python多处理模块正确创建子进程,而不会导致网页响应挂起。我已经尝试了几个最新版本的gunicorn,问题仍然存在。有趣的是,问题从来都不是ubuntu服务器上的问题,但现在将应用程序移到rhel6.5这个问题已经出现了。这是工作流程:

-route被击中了 -form被提交到命中路由并触发要创建的multiprocessing.Process(),其中完成的工作是睡30秒 - 路线似乎完成,作为打印多处理呼叫后的打印声明,但是浏览器保持连接打开并且不完成加载' (显示页面)直到睡眠完成30秒

请注意,表单提交不是此问题的一部分,它只是帮助查看问题。

这是一个非常简单的路线和功能,产生了问题:

def multi():
    print 'begin multi'
    time.sleep(30)
    print 'end multi'

@app.route('/multiprocesstest', methods=['GET','POST'])
def multiprocesstest():

    syntaxForm = forms.mainSyntaxForm()

    if syntaxForm.validate_on_submit():
        print 'before multi call'
        th = multiprocessing.Process(target=multi)
        th.start()
        print 'after multi call'
        return redirect('multiprocesstest')

    return render_template('syntax_main.html', form=syntaxForm)

经过长时间的研究和针对这个问题的稀疏谷歌搜索结果,我没有找到任何结论。我将尝试另一个负载均衡器来检查问题是仅仅是枪炮。

4 个答案:

答案 0 :(得分:2)

multiprocessing替换multiprocessing.dummy可能会解决问题,因为gunicornmultiprocessing都是多处理模块,当您尝试在内部调用多个进程时可能会遇到麻烦单一过程。

答案 1 :(得分:1)

好的,所以我在Flask / UWSGI / NGINX / Linux 14.04上遇到了这个问题。

未来读者的好消息:我能够解决这个问题。 坏消息:我很确定这是一个可怕的黑客。

一些有趣的测试代码,以证明这将永远挂起:

@app.route('/spin-up')
def spin_up():
  import multiprocessing as mp
  def spin_forever():
    while True:
      time.sleep(1)

  print('starting new process')
  p = mp.Process(target=spin_forever)
  print('created')
  p.start()
  print('started--generating result')
  return flask.render_template_string('awesome')

如果您点击端点'/ spin-up',它将启动该过程并永久挂起。太棒了,是吗?

基本消息队列不起作用,除非你完全进入进程外(即使用在已经启动的不同进程中运行的消息队列)或者不验证成功(即等待成功) ACK响应)。

简短的回答是,如果您尝试验证子流程是否成功,则会遇到麻烦。我在线程之间使用内部消息队列,如果我等待“成功”响应,Flask服务器仍然会挂起。如,

@app.route('/spin-up')
def spin_up():
  put_start_message_on_queue():
  while True:
    if got_success_response_from_queue():
      break
    time.sleep(0.1)
  return flask.render_template_string('awesome')

这仍然挂起(永远),所以我在消息队列中添加了第二个命令,称为'restart':

@app.route('/spin-up')
def spin_up():
  put_start_message_on_queue()
  while True:
    if got_success_message_from_queue():
      break
    time.sleep(0.1)
  put_restart_message_on_queue()
  return flask.render_template_string('awesome')

您必须确保restart_message在收到时会杀死现有进程,然后在启动新进程之前执行少量工作,甚至可能插入

time.sleep(0)
消息处理程序中的

。据我所知,这是一个巨大的问题,但它始终如一,只要重新启动过程(对不起,如果你不是这样的话......)

答案 2 :(得分:0)

我的节目也以类似的方式挂起。似乎Gevent和Multiprocessing.Process不能很好地协同工作。

答案 3 :(得分:0)

用 multiprocessing.dummy 作品替换 multiprocessing。它会在并发请求中加速应用程序,但不会为一个请求加速