Radzhab
@Radzhab

Asyncio очень медленно работает во Flask?

Есть 3 endpoint во flask, которая возвращает json. Есть 4-й endpoint, который асинхронно обращается к 3-м выше и собирает итоговый json. Всё работает, но очень медленно отрабатывают гет-запросы. Если вручную зайти - всё проходит быстро. Я ставлю таймаут 2 секунды, и у меня возвращается ответ только от 2-ого endpoint.

import aiohttp
import asyncio
import async_timeout
from flask import Flask,g
import json

class datas():
    def __init__(self,id,name) -> None:
        self.id = id
        self.name = name

urls = ['http://localhost:5555/url1',
        'http://localhost:5555/url2',
        'http://localhost:5555/url3']

app = Flask(__name__)

async def fetch_url(session, url):
    try:
        response = await session.get(url,timeout=2)
        text =await response.text()
        return text
    except Exception as e:
        return 'error'


def generate_json(fr,to):
    list = []
    for i in range(fr,to,1):
        list.append(datas(i, f'Test {i}') )
    return list    

def dump_list_to_json(items):
    return json.dumps(items, default = lambda x: x.__dict__)

@app.route('/url1')
def url1():
    item1 = generate_json(1,10)
    item2 = generate_json(31,40)

    return dump_list_to_json(item1+item2)

@app.route('/url2')
def url2():
    item1 = generate_json(11,20)
    item2 = generate_json(41,50)
    return dump_list_to_json(item1+item2)

@app.route('/url3')
def url3():
    item1 = generate_json(21,30)
    item2 = generate_json(51,60)
    return dump_list_to_json(item1+item2)

@app.route('/async_get_urls_v2')
async def async_get_urls_v2():
    async with aiohttp.ClientSession() as session:
        tasks = []
        for url in urls:
            task = asyncio.create_task(fetch_url(session, url))
            tasks.append(task)
        sites = await asyncio.gather(*tasks)

    items = []
    for site in sites:
        if not 'error' in site:
            j = json.loads(site)
            items.append(j)
            
    response = dump_list_to_json(items)
    return response

if __name__ == "__main__":
    app.run(debug=False, use_reloader=False, host='localhost', port=5555)
  • Вопрос задан
  • 85 просмотров
Решения вопроса 1
sergey-gornostaev
@sergey-gornostaev Куратор тега Асинхронное программирование
Седой и строгий
Flask разрабатывался синхронным и однопоточным. Любые попытки использования конкурентного выполнения в лучшем случае не дадут хороших результатов, а в худшем приведут к непредсказуемым и труднодиагностируемым ошибкам.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
2ord
@2ord
продвинутый чайник
Есть 3 endpoint во flask, которая возвращает json. Есть 4-й endpoint, который асинхронно обращается к 3-м выше и собирает итоговый json.
Зачем? Используй очередь сообщений и отдельный процесс для сбора данных с fetch_url. Клиент не должен ждать пока данные будут получены. Вместо этого для получения результатов можно использовать запросы short polling к серверу или сервер будет сам уведомлять через SSE.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы