我正在构建一个python flask服务,为此我尝试为每个单独的POST请求设置超时。 据我了解,只要有人向我的RESTful服务发送发布请求,就会有一个新线程(虚拟或真实)开始执行它。
现在,为了使我的服务器能够处理大量请求,如果进程运行的时间超过为每个POST方法设置的为其定义的恒定时间(TIMEOUT_TIME),我希望它返回超时响应,并停止执行那个单独的线程。
您能给我提出一个可以使用烧瓶方法实现的抽象方案吗?
答案 0 :(得分:0)
一种方法是在单独的进程中运行请求处理,如果超过超时则终止请求:
onRun
在此示例中,当睡眠java.lang.RuntimeException: java.lang.RuntimeException: java.lang.ClassNotFoundException: Class >com.learning.rackawareness.RackAwareness not found
at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:2227)
at org.apache.hadoop.hdfs.server.blockmanagement.DatanodeManager.<init>(DatanodeManager.java:208)
at org.apache.hadoop.hdfs.server.blockmanagement.BlockManager.<init>(BlockManager.java:268)
at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.<init>(FSNamesystem.java:737)
at org.apache.hadoop.hdfs.server.namenode.SecondaryNameNode.initialize(SecondaryNameNode.java:246)
at org.apache.hadoop.hdfs.server.namenode.SecondaryNameNode.<init>(SecondaryNameNode.java:192)
at org.apache.hadoop.hdfs.server.namenode.SecondaryNameNode.main(SecondaryNameNode.java:671)
Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: Class >com.learning.rackawareness.RackAwareness not found
at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:2195)
at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:2219)
... 6 more
Caused by: java.lang.ClassNotFoundException: Class >com.learning.rackawareness.RackAwareness not found
at org.apache.hadoop.conf.Configuration.getClassByName(Configuration.java:2101)
at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:2193)
... 7 more
小于给定的#!/usr/bin/env python3
import time
from multiprocessing import Process
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/api/sleep', methods=['POST'])
def sleep():
duration = int(request.args.get('duration', 1))
timeout = float(request.args.get('timeout', 2))
proc = Process(target=process_request, args=(duration,))
proc.start()
proc.join(timeout)
if proc.is_alive():
proc.terminate()
proc.join()
return jsonify(success=False, message='timeout exceeded'), 408
return jsonify(success=True, message='well done')
def process_request(t):
time.sleep(t)
if __name__ == '__main__':
app.run(host='localhost', port=8080, debug=True)
时,用户将获得成功的响应:
duration
否则,用户将收到timeout
错误:
curl -X POST http://localhost:8080/api/sleep?duration=1\&timeout=2
{
"message": "well done",
"success": true
}
中指出了这种方法的问题
请注意,退出处理程序和finally子句等将不会执行。
这意味着运行中的进程将无法在退出前进行清理,这可能会导致问题。另一种解决方案是使用特殊的408
线程,该线程将在以后超过超时的情况下用于加入工作进程或线程:
curl -X POST http://localhost:8080/api/sleep?duration=2\&timeout=1
{
"message": "timeout exceeded",
"success": false
}
在这里,在运行烧瓶服务器之前,已创建并启动Joiner
线程实例。服务器停止后,我们将#!/usr/bin/env python3
import time
from queue import Queue
from threading import Thread
from flask import Flask, request, jsonify
class Joiner(Thread):
def __init__(self):
super().__init__()
self.workers = Queue()
def run(self):
while True:
worker = self.workers.get()
if worker is None:
break
worker.join()
app = Flask(__name__)
@app.route('/api/sleep', methods=['POST'])
def sleep():
duration = int(request.args.get('duration', 1))
timeout = int(request.args.get('timeout', 2))
worker = Thread(target=process_request, args=(duration,))
worker.start()
worker.join(timeout)
if worker.is_alive():
joiner.workers.put(worker)
return jsonify(success=False, message='timeout exceeded'), 408
return jsonify(success=True, message='well done')
def process_request(t):
time.sleep(t)
if __name__ == '__main__':
joiner = Joiner()
joiner.start()
app.run(host='localhost', port=8080, debug=True)
joiner.workers.put(None)
joiner.join()
放入Joiner
队列中,以通知None
线程完成。