如何在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