由于 HTTP 规范,这在形式上是不可能的,但这里有一个棘手的解决方法。你可以使用stream:
烧瓶服务器
from flask import Flask, stream_with_context, request, jsonify, Response
from time import sleep
import json
app = Flask(__name__)
def destination1(param):
sleep(5)
return {"data": f"{param} from destination1"}
def destination2(param):
sleep(5)
return {"data": f"{param} from destination2"}
def destination3(param):
sleep(5)
return {"data": f"{param} from destination3"}
@app.route('/destination1', methods=['POST'])
def destination1_route():
return jsonify(destination1(request.json["param"]))
@app.route('/destination2', methods=['POST'])
def destination2_route():
return jsonify(destination2(request.json["param"]))
@app.route('/destination3', methods=['POST'])
def destination3_route():
return jsonify(destination3(request.json["param"]))
@app.route('/multi_destination', methods=['POST'])
def streamed_response():
destinations = request.json["destinations"]
def generate(destinations):
i = 0
last_element_num = len(destinations)-1
yield '[\n'
for destination in destinations:
if i == last_element_num:
yield json.dumps(eval(f'{destination["name"]}("{destination["param"]}")')) + '\n'
else:
yield json.dumps(eval(f'{destination["name"]}("{destination["param"]}")')) + ',\n'
i += 1
yield ']'
return app.response_class(stream_with_context(generate(destinations)), mimetype='application/json')
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000)
请求者
from time import time
import requests
json_data = {
"destinations": [
{"name": "destination1", "param": "param1"},
{"name": "destination2", "param": "param2"},
{"name": "destination3", "param": "param3"}
]
}
start_time = time()
r = requests.post('http://127.0.0.1:8000/multi_destination', json=json_data, timeout=7)
end_time = time()
print('Output:')
print(r.text)
print('HTTP response time:', r.elapsed.total_seconds())
print('Actually elapsed time:', end_time - start_time)
输出
Output:
[
{"data": "param1 from destination1"},
{"data": "param2 from destination2"},
{"data": "param3 from destination3"}
]
HTTP response time: 0.001916
Actually elapsed time: 15.01642894744873
因此,您可以看到总经过时间为 15 秒,但请求超时时间仅为 7 秒。总时间大于超时,因为我们每 5 秒获取一次数据块 (sleep(5))。因此,您可以通过定期发送一些数据来保持连接数小时和数天。
在我的requester 示例中,您必须等待所有数据传输完毕。如果您想从destination1 获得响应并开始处理它而不等待来自destination2 的响应,您可以使用iterable way 进行请求。在这种情况下,您将能够立即处理{"data": "param1 from destination1"}, 行,而无需等待下一个数据。
您也可以查看answer(客户端)以了解如何在下载所有数据时无需等待即可处理流块