我正在为我的网络服务编写健康检查端点。
如果组件正常工作,端点将调用一系列返回True
的函数:
如果所有组件都正常工作,则认为系统正在运行:
def is_health():
healthy = all(r for r in (database(), cache(), worker(), storage()))
return healthy
当事情不起作用时,这些功能可能需要很长时间才能返回。例如,如果数据库因查询速度慢而陷入困境,database()
可能需要30秒以上才能返回。
运行状况检查端点在Django视图的上下文中运行,在uWSGI容器内运行。如果请求/响应周期超过30秒,则该请求是harakiri-ed!
这是一个巨大的失败,因为我丢失了所有关于哪个组件花了很长时间记录的上下文信息。
我真正喜欢的是组件功能在超时或截止时间内运行:
with timeout(seconds=30):
database_result = database()
cache_result = cache()
worker_result = worker()
storage_result = storage()
在我的想象中,随着截止日期/ harakiri超时的临近,我可以中止剩余的健康检查,并只报告我完成的工作。
处理此类事情的正确方法是什么?
我查看了threading.Thread
和Queue.Queue
- 我的想法是创建工作和结果队列,然后使用线程来使用工作队列,同时将结果放在结果中队列。然后我可以使用线程的Thread.join
函数来停止处理其余的组件。
我面临的一个挑战是,我不确定如何努力退出线程 - 如果它没有完成它的运行,我不会希望它永远存在。 / p>
这是我到目前为止的代码。我是在正确的轨道上吗?
import Queue
import threading
import time
class WorkThread(threading.Thread):
def __init__(self, work_queue, result_queue):
super(WorkThread, self).__init__()
self.work_queue = work_queue
self.result_queue = result_queue
self._timeout = threading.Event()
def timeout(self):
self._timeout.set()
def timed_out(self):
return self._timeout.is_set()
def run(self):
while not self.timed_out():
try:
work_fn, work_arg = self.work_queue.get()
retval = work_fn(work_arg)
self.result_queue.put(retval)
except (Queue.Empty):
break
def work(retval, timeout=1):
time.sleep(timeout)
return retval
def main():
# Two work items that will take at least two seconds to complete.
work_queue = Queue.Queue()
work_queue.put_nowait([work, 1])
work_queue.put_nowait([work, 2])
result_queue = Queue.Queue()
# Run the `WorkThread`. It should complete one item from the work queue
# before it times out.
t = WorkThread(work_queue=work_queue, result_queue=result_queue)
t.start()
t.join(timeout=1.1)
t.timeout()
results = []
while True:
try:
result = result_queue.get_nowait()
results.append(result)
except (Queue.Empty):
break
print results
if __name__ == "__main__":
main()
更新
似乎在Python中你有一些选择可以实现这种性质的超时:
SIGALARMS
,但如果您在uWSGI
这样的容器中运行,可能会出错。uWSGI
),您可能需要设置选项以启用它们。AsyncResult
的{{1}}参数来约束执行。我正在探索这些不同选择的好处。
我整理了一个GitHub回购,其中包含有关该主题的更多信息:
我有一天会把它输入答案,但TLDR就在这里: