其他分享
首页 > 其他分享> > 如何在Cherrypy中停止请求处理?

如何在Cherrypy中停止请求处理?

作者:互联网

即时通讯使用python 2.6,cherrypy 3.1

我有一些问题超时请求.我只需要在Limit(30秒)内完成请求.在该限制之后,应该杀死进程并返回回答

服务器从tree.mount()开始; cherrypy.start(); cherrypy.block()

作为第一件事…当我试图杀死应用程序(通过Ctrl C(debian 6.0)),应用程序被卡住:

等待子线程终止…

如何在退出时终止进程以及如何处理超时连接以杀死未响应的进程?

我不能在这里写任何代码,因为它是严格专有的,无论如何,我希望有人已经解决了这个问题.

问候马丁

解决方法:

警告.如果您在正常执行流程中不小心杀死线程或进程,那么很可能会搞砸.如果Python代码除了并且最终不会执行,您将遇到内存和同步问题(例如死锁),未关闭的文件句柄和套接字等等.杀戮是解决你的问题的方法,就像断头台可能被称为治疗头皮屑一样.

用Python杀死一个线程

一般来说,你不能这样做.没有这样的API.对于某些情况你可以找到some hacks,但一般情况下你不能.终止线程的唯一稳定方法是通过标志,事件等与之合作.

强制停止CherryPy过程

当您在拥有CherryPy Python进程的终端中按Ctrl C时,解释器会收到SIGINT信号并引发KeyboardInterrupt异常.然后CherryPy命令其工作线程停止并告诉您等待子线程终止….如果工作线程在用户代码中被阻止,CherryPy将等到它被释放.

要强制停止,您可以使用common kill -9 PID,其中PID是您的CherryPy进程的进程ID.有时您可以使用任何过程监视器找到它.或者合并cherrypy.process.plugins.PIDFile以编写进程的pid文件.

处理可能无响应的任务

通常,CherryPy是一个线程服务器.如果您的任务有十几秒的响应,则很容易耗尽工作线程.在这种情况下,后台任务队列可能是一个好主意(Celery,Rq)或至少有一些使用cherrypy.process.plugins.BackgroundTask.但它显然会让你重新设计你的系统,进行临时结果存储,响应轮询或推送.它增加了复杂性,因此应该对所有利弊进行权衡.

如果您可以限制执行处理或计算的最终执行,那么最好在那里执行.无论是数据库,还是Web服务API调用,或者是什么,然后只处理超时异常.

CherryPy开箱即用的响应超时

CherryPy中的响应超时功能开箱即用.它由response.timeout配置和cherrypy._TimeoutMonitor控制,它在一个单独的线程中运行,并查看响应是否超时.虽然实际上监视器只设置了一个属性response.timed_out,稍后在cherrypy._cprequest.Request.run中查看该属性,如果它是真的,则会引发cherrypy.TimeoutError.因此事后提出了超时异常.如果您的页面处理程序阻塞了30秒,那么您将在30秒后获得异常.

#!/usr/bin/env python
# -*- coding: utf-8 -*-


import time

import cherrypy


config = {
  'global' : {
    'server.socket_host' : '127.0.0.1',
    'server.socket_port' : 8080,
    'server.thread_pool' : 8,
    # interval in seconds at which the timeout monitor runs
    'engine.timeout_monitor.frequency' : 1
  },
  '/' : {
    # the number of seconds to allow responses to run
    'response.timeout' : 2
  }
}


class App:

  @cherrypy.expose
  def index(self):
    time.sleep(8)
    print('after sleep')
    return '<em>Timeout test</em>'


if __name__ == '__main__':
  cherrypy.quickstart(App(), '/', config)

强制响应超时

你不能杀死一个线程,但你可以杀死一个进程.如果您无法以任何其他方式控制任务,则可以将执行包装在进程中并使用监视器在其用完时将其终止.以下说明了这个想法.

#!/usr/bin/env python
# -*- coding: utf-8 -*-


import os
import signal
import time
from multiprocessing import Process

import cherrypy


config = {
  'global' : {
    'server.socket_host' : '127.0.0.1',
    'server.socket_port' : 8080,
    'server.thread_pool' : 8,
    # disable internal timeout monitor
    'engine.timeout_monitor.on' : False,
    # interval in seconds at which the timeout monitor runs
    'engine.timeout_kill_monitor.frequency' : 1
  },
  '/' : {
    # the number of seconds to allow responses to run
    'response.timeout' : 2
  }
}


class TimeoutKillMonitor(cherrypy._TimeoutMonitor):

  def run(self):
    cherrypy._TimeoutMonitor.run(self)

    for request, response in self.servings:
      if response.timed_out and hasattr(response, 'jobProcess'):
        if response.jobProcess.is_alive():
          os.kill(response.jobProcess.pid, signal.SIGKILL)

cherrypy.engine.timeout_kill_monitor = TimeoutKillMonitor(cherrypy.engine)
cherrypy.engine.timeout_kill_monitor.subscribe()



def externalJob():
  time.sleep(8)

class App:

  @cherrypy.expose
  def index(self):
    p = Process(target = externalJob)
    p.start()

    cherrypy.response.jobProcess = p
    p.join()

    # To determine whether your job process has been killed
    # you can use ``killed = response.timed_out``. Reset it to
    # ``False`` to avoid ``TimeoutError`` and response a failure 
    # state in other way.

    return '<em>Result</em>'


if __name__ == '__main__':
  cherrypy.quickstart(App(), '/', config)

请注意,您不能使用multiprocessing.Queue或multiprocessing.Pipe与您的工作进程通信,因为当它被终止时,访问其中任何一个都将锁定您的CherryPy线程.以下是Process.terminate的Python文档的引用.

If this method is used when the associated process is using a pipe or queue then the pipe
or queue is liable to become corrupted and may become unusable by other process.
Similarly, if the process has acquired a lock or semaphore etc. then terminating it is
liable to cause other processes to deadlock.

所以是的,技术上可以强制超时,但这是一种沮丧和容易出错的方式.

标签:python,cherrypy
来源: https://codeday.me/bug/20191008/1873807.html