| Async trong Python & FastAPI

Được viết bởi thanhdt vào ngày 01/12/2025 lúc 14:23 | 33 lượt xem

Async trong Python & FastAPI: Lập trình bất đồng bộ từ A–Z

https://raw.githubusercontent.com/talkpython/async-techniques-python-course/master/readme_resources/async-python.png
https://media2.dev.to/dynamic/image/width%3D1000%2Cheight%3D420%2Cfit%3Dcover%2Cgravity%3Dauto%2Cformat%3Dauto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6bzcmzv9h4unl7z85huu.png
https://i.ytimg.com/vi/RlM9AfWf1WU/maxresdefault.jpg

4

Lập trình bất đồng bộ (asynchronous programming) là nền tảng giúp FastAPI đạt hiệu năng vượt trội so với nhiều framework Python truyền thống.
Bài viết này giúp bạn hiểu:

  • Async là gì & vì sao nó quan trọng
  • Khác nhau giữa blocking vs non-blocking
  • Coroutine, event loop hoạt động ra sao
  • FastAPI xử lý async thế nào
  • So sánh hiệu năng khi gọi API tuần tự vs song song

1. Async là gì? Tại sao phải dùng trong Backend?

Trong backend, phần lớn thời gian không phải CPU chạy code, mà là:

  • Chờ database trả về
  • Chờ API ngoài trả về
  • Chờ đọc file
  • Chờ network I/O

Các “khoảng chờ” này nếu dùng lập trình thông thường (blocking) sẽ làm tắc luồng, giảm throughput của server.

Async giải quyết vấn đề này bằng cách:

  • Không chặn luồng khi đang “chờ”
  • Cho phép server xử lý các request khác song song
  • Tận dụng tối đa tài nguyên khi hệ thống I/O nhiều
https://infonw.laurensstoop.nl/_images/sync_async.png
https://nikgrozev.com/images/blog/async-await/AsyncAwaitExample.png

2. Blocking vs Non-blocking – Khác nhau thế nào?

Blocking (truyền thống)

result = call_api()
process(result)

Trong lúc call_api() chờ phản hồi, toàn bộ hàm bị đứng lại → không làm gì được.


Non-blocking (async)

result = await call_api_async()
process(result)

Khi “chờ”, Python nhường quyền cho tác vụ khác → server có thể xử lý hàng trăm request cùng lúc.


3. Event Loop & Coroutine – Trái tim của Async

Coroutine

Một hàm có thể tạm dừng & tiếp tục chạy ở đúng vị trí cũ.

async def get_data():
    return 123

Event Loop

Bộ điều phối coroutine — quyết định hàm nào chạy tiếp, hàm nào tạm dừng để chờ I/O.

https://www.pythontutorial.net/wp-content/uploads/2022/07/python-event-loop.svg
https://blog.davidvassallo.me/wp-content/uploads/2020/01/image.png

FastAPI chạy trên ASGI (Asynchronous Server Gateway Interface), tận dụng tối đa event loop để xử lý concurrency.


4. Async trong FastAPI hoạt động như thế nào?

Ví dụ:

from fastapi import FastAPI

app = FastAPI()

@app.get("/user")
async def get_user():
    return {"name": "Thanh", "role": "Backend"}

Lưu ý:

  • Chỉ cần dùng async def → route của bạn trở thành bất đồng bộ
  • FastAPI sẽ dùng event loop để xử lý đồng thời nhiều request
  • Nếu hàm bên trong có await (như DB, API bên ngoài), server sẽ cực kỳ hiệu quả

5. Ví dụ thực tế: Gọi API tuần tự vs song song

Giả sử ta cần gọi 3 API khác nhau.

Cách 1 – Blocking (mất 3 giây)

import time
import requests

def call_api():
    res = requests.get("https://httpbin.org/delay/1")
    return res.status_code

start = time.time()
call_api()
call_api()
call_api()
print("Total:", time.time() - start)

Kết quả: khoảng 3 giây


Cách 2 – Async (chỉ ~1 giây)

import httpx
import asyncio
import time

async def call_api_async():
    async with httpx.AsyncClient() as client:
        r = await client.get("https://httpbin.org/delay/1")
        return r.status_code

async def main():
    start = time.time()
    await asyncio.gather(
        call_api_async(),
        call_api_async(),
        call_api_async()
    )
    print("Total:", time.time() - start)

asyncio.run(main())

Kết quả: ~1 giây
→ do cả 3 request thực thi cùng lúc.

https://www.baeldung.com/wp-content/uploads/sites/4/2024/02/concurrent-async.jpg
https://i0.wp.com/blog.blackfire.io/wp-content/uploads/2022/01/python-sync-flow.png?fit=512%2C196&ssl=1

6. Khi nào nên dùng async trong FastAPI?

✔ Dùng async khi:

  • Gọi database (PostgreSQL async driver, MongoDB, Redis…)
  • Gọi API ngoài (payment, trading, AI API…)
  • Đọc/ghi file
  • Xử lý nhiều request đồng thời
  • Viết microservices

✘ Không cần async khi:

  • Bạn xử lý CPU-bound (ML training, thuật toán nặng)
    → Dùng multiprocessing hoặc background tasks phù hợp hơn.

7. Lưu ý quan trọng khi dùng async trong FastAPI

1. Không mix requests (sync) trong async

Sai:

async def task():
    res = requests.get("http://...")

→ requests là thư viện sync → block event loop → mất hết lợi ích async.

Dùng httpx.AsyncClient.


2. ORM sync không tận dụng được async

Dùng SQLAlchemy sync trong async → kém hiệu quả.

Giải pháp:

  • SQLAlchemy Async
  • Tortoise ORM
  • Gino

8. Demo endpoint async thực tế trong FastAPI

import httpx
from fastapi import FastAPI

app = FastAPI()

@app.get("/prices")
async def get_prices():
    async with httpx.AsyncClient() as client:
        btc = await client.get("https://api.binance.com/api/v3/ticker/price?symbol=BTCUSDT")
        eth = await client.get("https://api.binance.com/api/v3/ticker/price?symbol=ETHUSDT")
    return {
        "btc": btc.json(),
        "eth": eth.json()
    }

Endpoint này xử lý đồng thời nhiều request tới Binance → nhanh hơn cực nhiều so với gọi tuần tự.


9. Minh họa kiến trúc FastAPI dùng Async

https://miro.medium.com/0%2AyGZ5EF4hsMe2JSOu
https://media2.dev.to/dynamic/image/width%3D1280%2Cheight%3D720%2Cfit%3Dcover%2Cgravity%3Dauto%2Cformat%3Dauto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6bzcmzv9h4unl7z85huu.png

10. Kết luận

  • Async giúp FastAPI mạnh hơn Flask/Django REST trong các hệ thống I/O-bound
  • Tối ưu tài nguyên server, tăng throughput
  • Rất phù hợp cho microservices, AI API, trading API, data API
  • Là kỹ năng bắt buộc nếu muốn code backend FastAPI một cách hiện đại và chuyên nghiệp

Tham khảo khóa học FastAPI thực chiến

👉 Python API Development với FastAPI
https://www.huongnghiepdulieu.com/python-fastapi/

Khóa học gồm:

  • Async & concurrency
  • CRUD + PostgreSQL + ORM
  • Authentication JWT
  • Upload file & xử lý media
  • Docker + Deploy
  • Project hoàn chỉnh