1 回答

TA貢獻1859條經驗 獲得超6個贊
這可以安全地在生產環境中運行,但 asyncio 無法與 Gunicorn 異步工作線程(例如 gevent 或 eventlet)有效配合。這是因為
result_a, result_b = asyncio.run(contact_apis())
將會阻止 gevent/eventlet 事件循環直到其完成,而使用 gevent/eventlet 生成等效項則不會。Flask 服務器不應該在生產中使用。Gunicorn 線程工作線程(或多個 Gunicorn 進程)會很好,因為 asyncio 會阻塞線程/進程。全局變量可以正常工作,因為它們與線程(線程工作線程)或綠色線程(gevent/eventlet)相關聯,而不是與 asyncio 任務相關聯。
我想說Quart是一種改進。Quart 是使用 asyncio 重新實現的 Flask API。對于 Quart,上面的代碼片段是:
import asyncio
import random
import time
from quart import Quart
? ??
app = Quart(__name__)
? ??
async def contact_api_a():
? ? print(f'{time.perf_counter()}: Start request 1')
? ? # This sleep simulates querying and having to wait for an external API
? ? await asyncio.sleep(2)
? ? # Here is our simulated API reply
? ? result = random.random()
? ? print(f'{time.perf_counter()}: Finish request 1')
? ? return result
? ??
async def contact_api_b():
? ? print(f'{time.perf_counter()}: Start request 2')
? ? await asyncio.sleep(1)
? ? result = random.random()
? ? print(f'{time.perf_counter()}: Finish request 2')
? ? return result
? ??
async def contact_apis():
? ? # Create the two tasks
? ? task_a = asyncio.create_task(contact_api_a())
? ? task_b = asyncio.create_task(contact_api_b())
? ? # Wait for both API requests to finish
? ? result_a, result_b = await asyncio.gather(task_a, task_b)
? ? print(f'{time.perf_counter()}: Finish both requests')
? ? return result_a, result_b
? ??
@app.route('/')
async def hello_world():
? ? start_time = time.perf_counter()
? ? # All async processes are organized in a separate function
? ? result_a, result_b = await contact_apis()
? ? # We implement some final business logic before finishing the request
? ? final_result = result_a + result_b
? ? processing_time = time.perf_counter() - start_time
? ? return f'Result: {final_result:.2f}; Processing time: {processing_time:.2f}'
我還建議使用基于 asyncio 的請求庫,例如httpx
添加回答
舉報