← Назад к вопросам

Асинхронен ли asgi

1.8 Middle🔥 111 комментариев
#FastAPI и Flask#Асинхронность и многопоточность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Асинхронен ли ASGI?

Ответ: Не совсем. ASGI (Asynchronous Server Gateway Interface) поддерживает асинхронность, но сама по себе не является асинхронной. Это спецификация, которая может работать как синхронно, так и асинхронно.

Что такое ASGI?

ASGI - это стандарт взаимодействия между веб-сервером и Python приложением для работы с HTTP, WebSocket и других асинхронных протоколов. Это как WSGI (для синхронных приложений), но расширенный для поддержки асинхронности.

WSGI и ASGI: Основные отличия

WSGI (Synchronous)

ВSGI - это синхронный интерфейс. Каждый запрос обрабатывается отдельным процессом или потоком. Пока обрабатывается один запрос, он полностью блокирует ресурс.

def application(environ, start_response):
    status = "200 OK"
    response = b"Hello World"
    start_response(status, [("Content-Type", "text/plain")])
    return [response]

ASGI (Может быть асинхронным или синхронным)

ASGI - это спецификация, которая позволяет ASGI приложению быть как асинхронным, так и синхронным:

# Асинхронное ASGI приложение
async def application(scope, receive, send):
    await send({
        "type": "http.response.start",
        "status": 200,
        "headers": [[b"content-type", b"text/plain"]],
    })
    await send({
        "type": "http.response.body",
        "body": b"Hello World",
    })

# Синхронное ASGI приложение - тоже допустимо!
def application(scope, receive, send):
    send({
        "type": "http.response.start",
        "status": 200,
    })
    send({
        "type": "http.response.body",
        "body": b"Hello World",
    })

ASGI поддерживает ОБА типа кода

Это критически важное понимание: ASGI сервер (вроде Uvicorn, Hypercorn) может работать как с асинхронным, так и с синхронным кодом приложения.

Пример с FastAPI - асинхронный

from fastapi import FastAPI
import aiohttp

app = FastAPI()

@app.get("/users/{user_id}")
async def get_user(user_id: int):
    async with aiohttp.ClientSession() as session:
        async with session.get(f"https://api.example.com/users/{user_id}") as resp:
            data = await resp.json()
            return data

Пример с FastAPI - синхронный

from fastapi import FastAPI
import requests

app = FastAPI()

@app.get("/users/{user_id}")
def get_user(user_id: int):
    response = requests.get(f"https://api.example.com/users/{user_id}")
    return response.json()

Второй код тоже будет работать в ASGI приложении, но менее эффективно.

Как ASGI сервер обрабатывает синхронный код?

Когда вы используете синхронную функцию в ASGI приложении, Uvicorn запускает её в отдельном потоке, чтобы не блокировать event loop:

import asyncio
from concurrent.futures import ThreadPoolExecutor

# Внутри Uvicorn
async def handle_sync_endpoint(endpoint_func):
    loop = asyncio.get_event_loop()
    result = await loop.run_in_executor(
        ThreadPoolExecutor(),
        endpoint_func
    )
    return result

Так что синхронный код выполняется в отдельном потоке, не блокируя главный event loop.

ASGI - это про ИНТЕРФЕЙС, не про асинхронность

ASGI - это способ обмена информацией между сервером и приложением через три параметра:

async def app(scope, receive, send):
    # scope - информация о запросе (метод, путь, заголовки)
    # receive - функция для получения событий от сервера
    # send - функция для отправки событий к серверу
    
    if scope["type"] == "http":
        body = b""
        while True:
            message = await receive()
            if message["type"] == "http.request":
                body += message.get("body", b"")
                if not message.get("more_body", False):
                    break
        
        await send({
            "type": "http.response.start",
            "status": 200,
        })
        await send({
            "type": "http.response.body",
            "body": b"Response: " + body,
        })

Сравнение WSGI и ASGI

ПараметрWSGIASGI
НазначениеHTTP толькоHTTP, WebSocket, другие
СинхронностьТолько синхронныйОба типа кода
ПроизводительностьПроцессы/потокиEvent loop
Примеры серверовGunicornUvicorn, Hypercorn
Примеры фреймворковFlask, DjangoFastAPI, Starlette

Реальный пример: FastAPI

from fastapi import FastAPI

app = FastAPI()

@app.get("/async")
async def async_endpoint():
    import asyncio
    await asyncio.sleep(1)
    return {"type": "async"}

@app.get("/sync")
def sync_endpoint():
    import time
    time.sleep(1)
    return {"type": "sync"}

Оба работают. Но асинхронный лучше - он не блокирует event loop.

Проблемы синхронного кода в ASGI

Хотя синхронный код работает, он имеет недостатки:

# Плохо - блокирует event loop
@app.get("/slow")
def slow_endpoint():
    import time
    time.sleep(10)  # Блокирует!
    return {"status": "done"}

# Хорошо - не блокирует event loop
@app.get("/fast")
async def fast_endpoint():
    import asyncio
    await asyncio.sleep(10)  # Не блокирует
    return {"status": "done"}

Вывод

ASGI сам по себе НЕ асинхронен. Это просто спецификация интерфейса. Но ASGI поддерживает асинхронность и может работать с обоими типами кода. Для максимальной производительности ASGI приложение должно использовать асинхронный код с async/await.