2014-02-03 4 views
2

im using python 2.6, cherrypy 3.1Как остановить обработку запросов на Cherrypy?

У меня есть проблема с таймаутом запросов. Мне просто нужно делать запросы в Limit (30 секунд). после этого предела процессы должны быть убиты и ответ будет возвращен

сервер запускается через tree.mount(); cherrypy.start(); cherrypy.block()

, как первое, что ... когда я пытаюсь убить приложение (с помощью клавиш Ctrl + C (Debian 6.0)), приложение застрял на:

Ожидание ребенка темы прекратить .. .

как убить процессы при выходе и как обрабатывать соединение с таймаутом для killin процесса, который не отвечает?

Я не могу написать здесь какой-либо код, потому что он строго проприетарный, во всяком случае, я надеюсь, что кто-то решил эту проблему еще.

Привет Мартин

ответ

3

Внимание. Весьма вероятно, что вы испортите вещи, если вы небрежно уничтожаете потоки или процессы как часть обычного потока выполнения. В случае кода Python except и finally не будут выполняться, у вас будут проблемы с памятью и синхронизацией (например, взаимоблокировки), открытые дескрипторы файлов и сокеты и т. Д. И т. Д. Killing - это решение вашей проблемы, так как гильотина может быть названа лекарством от перхоти.

Убийство нитку в Python

В общем вы не можете сделать это. Просто нет такого API. Вы можете найти some hacks для некоторых случаев, но в целом вы не можете. Единственный стабильный способ прекратить поток должен взаимодействовать с ним флагов, событий и т.д.

Force-стоп CherryPy процесс

При нажатии Ctrl +C в терминале, который владеет процессом CherryPy Python интерпретатор получает сигнал SIGINT и выдает исключение KeyboardInterrupt. Затем CherryPy приказывает своим рабочим потокам останавливаться и сообщает вам Ожидание окончания дочерних потоков .... Если рабочий поток заблокирован в коде пользователя, CherryPy будет ждать, пока он не будет выпущен.

Для принудительной остановки вы можете использовать общие kill -9 PID, где PID - это идентификатор процесса вашего процесса CherryPy. Иногда вы можете найти его с помощью любого монитора процесса. Или введите cherrypy.process.plugins.PIDFile, чтобы написать файл pidfile.

Обработка потенциально не отвечающие задачи

В общем CherryPy представляет собой резьбовой сервер. Если в ваших задачах используется десяток секунд, вы можете легко запустить рабочие потоки. В таком случае фоновая задача может быть хорошей идеей (Celery, Rq) или, по крайней мере, с использованием cherrypy.process.plugins.BackgroundTask. Но это, очевидно, заставляет вас перепроектировать вашу систему, сделать временное хранилище результатов, опросить опрос или нажать. Это добавляет сложности, поэтому решение должно быть принято взвешивать все плюсы и минусы.

Если вы можете ограничить выполнение на конце, которое выполняет обработку или расчет, вам лучше сделать это. Будь то база данных, или API-интерфейс веб-сервиса, или еще что-то, а затем просто обрабатывать исключение тайм-аута.

CherryPy вне коробки ожидания ответа

Существует ответ тайм-аут в CherryPy из коробки. Он управляется конфигурацией response.timeout и cherrypy._TimeoutMonitor, которая запускается в отдельном потоке и проверяет, был ли отсрочен ответ. Хотя на самом деле монитор устанавливает только атрибут, response.timed_out, который позже просматривается в cherrypy._cprequest.Request.run, и если это правда, то cherrypy.TimeoutError поднят. Таким образом, исключение с учетом таймаута повышается после factum. Если ваш обработчик страницы блокируется в течение 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 нить. Вот цитата из документации Python для Process.terminate.

Если этот метод используется, когда связанный с ним процесс использует трубу или очередь затем трубу или очередь несет ответственность повредиться и может стать непригодным для использования другим процессом. Аналогично, если процесс приобрел блокировку или семафор и т. Д., То завершение этого - , что может привести к взаимоблокировке других процессов.

Да, технически возможно заставить тайм-аут, но это обескураженный и подверженный ошибкам способ.

Смежные вопросы