如何限制请求执行时间?



我应该在 3 秒内给出答复。

我的处理程序与第三方服务器对话,该服务器可以在 3 秒内回复或无法回复。

我想到下面的代码——

class MainReply(webapp2.RequestHandler):
def get(self):
# do something
# start task to talk with 3rd server
for i in range(300): # wait 3 seconds
# check task status
# if finished, then break
time.sleep(0.01)
# if not finished, inform user

这是正确的方法吗?还是有更好的解决方案?

更新。我正在开发语音助手机器人(类似于谷歌助理(,机器人必须在 3 秒内回复。并且机器人无法自行启动答案,即一旦请求完成,我就无法给出另一个答案。而且由于这是语音助手,我不能给出链接。我在考虑以下方法——如果我能在 3 秒内给出一个正常的答案,那就给出它。如果没有 - 要求用户使用简单的单词(如"状态"(再次询问。

基本规则是你永远不应该像你的帖子中描述的那样做一个池,因为(1(你"手动"阻止了比需要更多的资源(2(你搞砸了模拟异步代码的代码,而实际上并非如此,(3(语言通常提供处理并发编程的工具,这些工具专门用于此类任务, 这比您实现它(在大多数情况下(要好得多。

遵循您的要求。我写了一个简单的程序,你可以测试。查看此处以获取asyncio.wait_for文档。在这里还可以找到一些有用的异步指南。

将代码复制到文件中并运行$ python [filename]

import asyncio
import random
from concurrent.futures._base import TimeoutError
async def safe_get():
result = "I'm currently out of my office."
try:
result = await asyncio.wait_for(get(), 3)
except TimeoutError as e:
print("Responder thought too much about his answer")
return result
async def get(a=1,b=6):
random_time = random.randint(a,b)
await asyncio.sleep(random_time)
return "I'm doing good thanks! Sorry it took me " + str(random_time) + "s to answer."
async def main():
# Toggle comment on the two following lines to see (1) unwanted behaviour and (2) wanted behaviour
# response = await get()
response = await safe_get()
print(response)
if __name__ == "__main__":
asyncio.run(main())

除了有问题的用户体验(响应缓慢,并且可能不是用户正在等待的响应(之外,这种方法还会给服务器的完整性带来风险:对于每个挂起的请求,您的服务器将使用资源,如果传入请求峰值较高,它可能会在其可用池或资源(如果有限(上运行,或者可能会增加您的成本(例如,通过启动额外的实例来跟上其他传入请求(如果配置为自动缩放(。

通常,对于可能需要很长时间的请求,最好立即回复挂起请求的 ID 和补充 URL,客户端可以在其中检查请求状态并最终获得预期的响应(如果可用(。您的服务器将负责 - 在后台,而不是在原始传入请求线程上 - 从第三方服务器获取答案。通过这种方式,您可以处理任何类型的请求,这些请求可能需要很长时间才能从第三方或内部处理中获得答案。

您是否通过http与该第三方服务器通信? 你能在python请求中使用timeout参数吗?

class MainReply(webapp2.RequestHandler):
def get(self):
# do something
try:
r = requests.post(... , timeout=3)
# finished, inform user
except requests.exceptions.Timeout:
# not finished, inform user

最新更新