--如何优雅地关闭TProcessPoolServer? --我还没有找到任何文档、示例或博客文章。到目前为止,以下是我的经历。
我是直接在命令行./ thrift _service.py上运行我的节俭服务器,而不是在主管下运行。我使用python2.6和节俭0.8.0。
我最初尝试过:
server = TProcessPoolServer(processor, transport, tfactory, pfactory)
try:
server.serve()
finally:
server.stop()当我发送σ--父python进程时,我在输出中看到“终止”,进程被终止,但是它的子进程是孤立的,并且继续运行。
然后我偶然发现了节约服务器测试,并试着:
import signal
def set_alarm(server):
def clean_shutdown(signum, frame):
for worker in server.workers:
logging.error("Terminating worker: {0}".format(worker))
worker.terminate()
logging.error("Requesting server to stop()")
try:
server.stop()
except (KeyboardInterrupt, SystemExit):
pass
except Exception as err:
logging.exception(err)
def logme(s, *args, **kwargs):
logging.error(">>> {0} <<<".format(s))
clean_shutdown(*args, **kwargs)
signal.signal(signal.SIGALRM, clean_shutdown)
signal.signal(signal.SIGHUP, clean_shutdown)
signal.signal(signal.SIGINT, clean_shutdown)
signal.signal(signal.SIGTERM, lambda x, y: logme("SIGTERM", x, y))
server = TProcessPoolServer(processor, transport, tfactory, pfactory)
set_alarm(server)
server.serve()当我向父python进程发送σ、sigalrm、sighup或sigint时,服务器将停止接受连接,但进程不会终止。
在输出中我看到:
ERROR:root:>>> SIGTERM <<<
ERROR:root:Terminating worker: <Process(Process-1, started daemon)>
ERROR:root:Terminating worker: <Process(Process-2, started daemon)>
ERROR:root:Terminating worker: <Process(Process-3, started daemon)>
ERROR:root:Terminating worker: <Process(Process-4, started daemon)>
ERROR:root:Terminating worker: <Process(Process-5, started daemon)>
ERROR:root:Requesting server to stop()这是意料之中的,但随后信号再次被捕获,进程不再处于启动状态,服务器被要求停止。这部分发生了大约十次,然后没有更多的输出。
ERROR:root:>>> SIGTERM <<<
ERROR:root:Terminating worker: <Process(Process-1, unknown daemon)>
ERROR:root:Requesting server to stop()有时,我从多处理库中看到一个AssertionError:
Traceback (most recent call last):
File "/path/to/thrift_service.py", line 340, in clean_shutdown
server.stop()
File "/usr/local/lib/python2.6/dist-packages/thrift/server/TProcessPoolServer.py", line 123, in stop
self.stopCondition.notify()
File "/usr/lib/python2.6/multiprocessing/synchronize.py", line 223, in notify
assert not self._wait_semaphore.acquire(False)
AssertionError发布于 2012-05-25 16:58:29
我使用信号和它公开的TProcessPoolServer为python中的postForkCallback添加了一个优雅的关机。一旦初始化,TProcessPoolServer将在每个工作进程中调用您的postForkCallback。这允许您设置信号处理程序并优雅地关闭。由于工作人员捕获了SystemExit或KeyboardInterruptException异常,您可以为SIGINT设置一个处理程序,然后在清理完调用sys.exit(0)之后,这将导致工作人员关闭。
import signal
import sys
def setupHandlers():
signal.signal(signal.SIGINT, handleSIGINT)
#Optionally if you want to keep the current socket connection open and working
#tell python to make system calls non-interruptable, which is probably what you want.
signal.siginterrupt(signal.SIGINT, False)
def handleSIGINT(sig, frame):
#clean up state or what ever is necessary
sys.exit(0)
server = TProcessPoolServer(processor, transport, tfactory, pfactory)
server.setPostForkCallback(setupHandlers)
#Setup handlers in main process too
setupHandlers()
#Start server
server.start()这样,生成的每个辅助进程都会设置信号处理程序,以正确处理优雅的关机。在本例中,我为主进程设置了相同的处理程序,也为可能根据用例工作的工作人员设置了相同的处理程序,但如果需要,您可以轻松地为主进程定义不同的处理程序。请记住,处理程序将从每个进程的上下文中调用,这样您就无法在清理期间跨进程共享状态。
有关http://docs.python.org/library/signal.html做什么以及为什么需要它的更多细节,请参见signal.siginterrupt。
编辑:您将需要使用Crtl +C向所有进程发送SIGINT信号,或者如果它作为守护进程运行,则杀死所有进程的-SIGINT pids。
您可以很容易地使用ps -ppid父pid获取工人的pids。
发布于 2021-04-13 07:34:26
程序启动后,我记录了主进程的进程号。然后根据ps --ppid,返回主进程的子进程,然后逐个杀死它们。
我的服务的控制shell脚本的代码:
function stop
{
SERVER_PID=`cat logs/server.pid`
SPIDS=`ps --ppid $SERVER_PID | awk '{if ($1!="PID") print $1}'`
kill -9 $SERVER_PID
for PID in $SPIDS
do
kill -9 $PID
done
}https://stackoverflow.com/questions/10689772
复制相似问题