03-1. 案例:I/O 密集型應用

API 網關、微服務、數據庫密集型應用的最佳配置

🎯 本章重點

學習如何為 I/O 密集型應用配置 Gunicorn,這是最常見的 Web 應用類型。

📊 什麼是 I/O 密集型應用?

定義

I/O 密集型應用:大部分時間在等待外部資源響應,而不是 CPU 計算。

一個請求的時間分配:

總時間:1000ms
├── CPU 計算:50ms (5%)      ← 很少
└── I/O 等待:950ms (95%)     ← 大部分時間
    ├── 資料庫查詢:400ms
    ├── Redis 讀取:100ms
    ├── 外部 API 調用:350ms
    └── 文件讀寫:100ms

典型特徵

# I/O 密集型應用的特徵

 大量外部調用
   - 數據庫查詢PostgreSQLMySQLMongoDB
   - 緩存讀寫RedisMemcached
   - 外部 API 調用支付簡訊天氣 API
   - 文件操作讀寫上傳下載
   - 消息隊列RabbitMQKafka

 響應時間特徵
   - 平均響應時間100-500ms
   - P95 響應時間500ms-2s
   - 時間主要花在等待而非計算

 不是 I/O 密集型
   - 影像處理resize濾鏡
   - 視頻轉碼
   - 大量數學計算
   - 機器學習推理
   - 加密解密大量數據

🏗️ 典型場景

場景 1:API 網關

# myapp/views.py
import httpx
from django.http import JsonResponse

async def api_gateway_view(request):
    """
    API 網關:需要調用多個外部服務
    這是典型的 I/O 密集型場景
    """
    async with httpx.AsyncClient() as client:
        # 並發調用多個服務
        user_task = client.get('http://user-service/api/user/123')
        order_task = client.get('http://order-service/api/orders?user=123')
        product_task = client.get('http://product-service/api/products')

        # 等待所有請求完成
        user_resp, order_resp, product_resp = await asyncio.gather(
            user_task,
            order_task,
            product_task
        )

    return JsonResponse({
        'user': user_resp.json(),
        'orders': order_resp.json(),
        'products': product_resp.json(),
    })

時間分析:

同步方式(WSGI Sync Worker):
├── 調用 user-service:300ms
├── 調用 order-service:400ms
├── 調用 product-service:350ms
└── 總時間:1050ms

異步方式(ASGI Uvicorn Worker):
├── 並發調用三個服務
└── 總時間:400ms (最慢的那個)

性能提升:1050ms → 400ms = 2.6x 快!

場景 2:數據庫密集型應用

# myapp/views.py
from django.db import models
from django.http import JsonResponse

class Order(models.Model):
    user = models.ForeignKey('User', on_delete=models.CASCADE)
    product = models.ForeignKey('Product', on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

async def order_list_view(request):
    """
    數據庫密集型:大量查詢和關聯
    """
    # 異步 ORM 查詢(Django 4.1+)
    orders = await Order.objects.select_related(
        'user', 'product'
    ).prefetch_related(
        'items', 'payments'
    ).filter(
        created_at__gte=timezone.now() - timedelta(days=30)
    ).aall()  # Django 4.1+ 異步查詢

    return JsonResponse({
        'orders': [
            {
                'id': order.id,
                'user': order.user.name,
                'product': order.product.name,
                'total': order.total,
            }
            for order in orders
        ]
    })

I/O 等待分析:

單個請求的時間:
├── Django 處理:20ms (CPU)
├── 資料庫查詢:
│   ├── 主查詢:150ms
│   ├── select_related:100ms
│   └── prefetch_related:120ms
├── Python 序列化:30ms (CPU)
└── 總時間:420ms

其中 I/O 等待:370ms (88%)
     CPU 計算:50ms (12%)

結論:典型的 I/O 密集型!

場景 3:微服務架構

# myapp/services.py
import httpx
from django.core.cache import cache

class UserService:
    """用戶微服務客戶端"""

    async def get_user(self, user_id):
        # 先查緩存
        cache_key = f'user:{user_id}'
        user = cache.get(cache_key)
        if user:
            return user

        # 緩存未命中,調用 API
        async with httpx.AsyncClient() as client:
            resp = await client.get(
                f'http://user-service/users/{user_id}'
            )
            user = resp.json()

        # 寫入緩存
        cache.set(cache_key, user, timeout=300)
        return user

async def dashboard_view(request):
    """儀表板:整合多個微服務數據"""
    service = UserService()

    # 並發調用
    user_data = await service.get_user(request.user.id)
    stats_data = await fetch_user_stats(request.user.id)
    recent_activity = await fetch_recent_activity(request.user.id)

    return render(request, 'dashboard.html', {
        'user': user_data,
        'stats': stats_data,
        'activity': recent_activity,
    })

⚙️ I/O 密集型應用的最佳配置

推薦配置(Django 3.0+)

# gunicorn.conf.py - I/O 密集型應用專用配置
import multiprocessing
import os

# ===== Worker 配置 =====
# I/O 密集型:使用 ASGI 異步 Worker
bind = "0.0.0.0:8000"
workers = multiprocessing.cpu_count()  # CPU 核心數即可
worker_class = "uvicorn.workers.UvicornWorker"  # 異步 Worker
worker_connections = 1000  # 每個 worker 的並發連接數

# ===== 超時配置 =====
# I/O 密集型應用通常需要較長的超時時間
timeout = 120  # 2 分鐘(考慮外部 API 可能很慢)
graceful_timeout = 30
keepalive = 20  # 較長的 keepalive 適合持久連接

# ===== 防止記憶體洩漏 =====
max_requests = 2000
max_requests_jitter = 200

# ===== 性能優化 =====
preload_app = True
worker_tmp_dir = "/dev/shm"

# ===== 日誌配置 =====
loglevel = "info"
accesslog = "/var/log/gunicorn/access.log"
errorlog = "/var/log/gunicorn/error.log"
access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s" %(D)s'

# ===== Hooks =====
def post_fork(server, worker):
    """Worker 初始化時關閉資料庫連接"""
    from django import db
    db.connections.close_all()
    server.log.info(f"Worker {worker.pid} spawned (I/O intensive mode)")

def worker_exit(server, worker):
    from django import db
    db.connections.close_all()
    server.log.info(f"Worker {worker.pid} exited")

為什麼這樣配置?

# 1. Workers 數量:CPU 核心數
workers = multiprocessing.cpu_count()

# 原因:
# - ASGI 異步模型,一個 worker 可處理數千並發
# - I/O 等待時,worker 不會閒置,會處理其他請求
# - 不需要像 Sync Worker 那樣 (2 × CPU + 1)

# 例如 4 核 CPU:
# - Sync Worker 需要:(2 × 4) + 1 = 9 個
# - Async Worker 只需:4 個
# - 但並發處理能力更強!

# 2. Worker 類型:Uvicorn
worker_class = "uvicorn.workers.UvicornWorker"

# 原因:
# - 原生支援 async/await
# - 高效的事件循環(asyncio)
# - 一個 worker 可同時處理數千個 I/O 等待的請求

# 3. 較長的 timeout
timeout = 120

# 原因:
# - 外部 API 可能響應慢
# - 數據庫複雜查詢可能需要時間
# - 防止正常的慢請求被誤殺

# 4. 較長的 keepalive
keepalive = 20

# 原因:
# - I/O 密集型應用適合持久連接
# - 減少 TCP 握手開銷
# - 提高性能

📈 性能測試對比

測試場景設定

# test_app/views.py
import asyncio
import httpx
from django.http import JsonResponse

# 模擬 I/O 密集型視圖
async def io_intensive_view(request):
    """模擬調用 3 個外部服務,每個需要 300ms"""
    async with httpx.AsyncClient() as client:
        tasks = [
            client.get('http://httpbin.org/delay/0.3'),
            client.get('http://httpbin.org/delay/0.3'),
            client.get('http://httpbin.org/delay/0.3'),
        ]
        results = await asyncio.gather(*tasks)

    return JsonResponse({'status': 'ok', 'count': len(results)})

# 同步版本(用於對比)
def sync_io_intensive_view(request):
    """同步版本:按順序調用"""
    import requests
    results = []
    for i in range(3):
        resp = requests.get('http://httpbin.org/delay/0.3')
        results.append(resp.json())

    return JsonResponse({'status': 'ok', 'count': len(results)})

測試結果

使用 Apache Bench 測試:

# 測試命令
ab -n 1000 -c 100 http://localhost:8000/api/test/

配置 1:Sync Worker (WSGI)

# gunicorn.conf.py
workers = 9  # (2 × 4) + 1
worker_class = "sync"

測試結果:

Concurrency Level:      100
Time taken for tests:   30.521 seconds
Complete requests:      1000
Failed requests:        0
Requests per second:    32.76 [#/sec]
Time per request:       3052.1 [ms]

分析:
- 每個請求需要 900ms (3 × 300ms 串行)
- 9 個 workers 同時只能處理 9 個請求
- 非常慢!❌

配置 2:Async Worker (ASGI)

# gunicorn.conf.py
workers = 4
worker_class = "uvicorn.workers.UvicornWorker"

測試結果:

Concurrency Level:      100
Time taken for tests:   3.142 seconds
Complete requests:      1000
Failed requests:        0
Requests per second:    318.27 [#/sec]
Time per request:       314.2 [ms]

分析:
- 每個請求實際只需要 300ms (3 個並發)
- 4 個 workers 可同時處理 400+ 並發請求
- 快 9.7 倍!✅

配置 3:Gevent Worker (遺留方案)

# gunicorn.conf.py
workers = 9
worker_class = "gevent"
worker_connections = 1000

測試結果:

Concurrency Level:      100
Time taken for tests:   4.521 seconds
Complete requests:      1000
Failed requests:        0
Requests per second:    221.19 [#/sec]
Time per request:       452.1 [ms]

分析:
- 比 Sync 快,但比 ASGI 慢
- Gevent 協程切換有開銷
- 不推薦新專案使用 ⚠️

性能對比總結

Worker 類型WorkersRPS平均響應時間相對性能
Sync (WSGI)932.763052ms1x (基準)
Gevent9221.19452ms6.7x
Uvicorn (ASGI)4318.27314ms9.7x

結論:I/O 密集型應用使用 ASGI,性能提升近 10 倍!


🔧 實戰案例:電商 API 服務

業務場景

電商平台的商品詳情頁 API:
├── 查詢商品資訊(PostgreSQL)
├── 查詢庫存(Redis)
├── 查詢價格(外部價格服務)
├── 查詢推薦商品(推薦引擎 API)
└── 查詢用戶收藏狀態(MongoDB)

預估流量:1000 QPS
平均響應時間要求:< 200ms

應用代碼

# ecommerce/views.py
import asyncio
import httpx
from django.http import JsonResponse
from django.core.cache import cache
from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=200)
    description = models.TextField()
    price = models.DecimalField(max_digits=10, decimal_places=2)

async def product_detail_view(request, product_id):
    """商品詳情 API - I/O 密集型"""

    # 並發執行多個 I/O 操作
    product_task = get_product_info(product_id)
    stock_task = get_stock_from_redis(product_id)
    price_task = get_price_from_service(product_id)
    recommend_task = get_recommendations(product_id)
    favorite_task = check_user_favorite(request.user.id, product_id)

    # 等待所有任務完成
    product, stock, price, recommendations, is_favorite = await asyncio.gather(
        product_task,
        stock_task,
        price_task,
        recommend_task,
        favorite_task,
        return_exceptions=True  # 某個服務失敗不影響其他
    )

    return JsonResponse({
        'product': {
            'id': product.id,
            'name': product.name,
            'description': product.description,
        },
        'stock': stock if not isinstance(stock, Exception) else 0,
        'price': price if not isinstance(price, Exception) else product.price,
        'recommendations': recommendations if not isinstance(recommendations, Exception) else [],
        'is_favorite': is_favorite if not isinstance(is_favorite, Exception) else False,
    })


async def get_product_info(product_id):
    """查詢商品資訊(約 80ms)"""
    # Django 4.1+ 異步 ORM
    return await Product.objects.aget(id=product_id)


async def get_stock_from_redis(product_id):
    """從 Redis 查詢庫存(約 10ms)"""
    from django.core.cache import cache
    stock = cache.get(f'stock:{product_id}')
    return stock if stock is not None else 0


async def get_price_from_service(product_id):
    """調用外部價格服務(約 150ms)"""
    async with httpx.AsyncClient(timeout=2.0) as client:
        try:
            resp = await client.get(
                f'http://price-service/api/price/{product_id}'
            )
            return resp.json()['price']
        except:
            return None


async def get_recommendations(product_id):
    """調用推薦引擎(約 200ms)"""
    async with httpx.AsyncClient(timeout=3.0) as client:
        try:
            resp = await client.get(
                f'http://recommend-service/api/recommend/{product_id}'
            )
            return resp.json()['products']
        except:
            return []


async def check_user_favorite(user_id, product_id):
    """查詢用戶收藏(約 50ms)"""
    # 假設使用 MongoDB
    from motor.motor_asyncio import AsyncIOMotorClient
    client = AsyncIOMotorClient('mongodb://localhost:27017')
    db = client.ecommerce

    favorite = await db.favorites.find_one({
        'user_id': user_id,
        'product_id': product_id
    })

    return favorite is not None

Gunicorn 配置

# gunicorn.conf.py
import multiprocessing

# 伺服器規格:8 核 CPU,16GB RAM
bind = "0.0.0.0:8000"
workers = 8  # = CPU 核心數
worker_class = "uvicorn.workers.UvicornWorker"
worker_connections = 1000

# 超時配置
timeout = 120
graceful_timeout = 30
keepalive = 20

# 防止記憶體洩漏
max_requests = 3000
max_requests_jitter = 300

# 性能優化
preload_app = True
worker_tmp_dir = "/dev/shm"

# 日誌
loglevel = "warning"
accesslog = "/var/log/gunicorn/ecommerce-access.log"
errorlog = "/var/log/gunicorn/ecommerce-error.log"

# Hooks
def post_fork(server, worker):
    from django import db
    from django.core.cache import cache

    # 關閉資料庫連接
    db.connections.close_all()

    # 測試 Redis 連接
    try:
        cache.get('health_check')
    except Exception as e:
        server.log.error(f"Redis connection failed: {e}")

    server.log.info(f"Worker {worker.pid} ready for I/O intensive workload")

性能測試結果

# 使用 wrk 進行壓測
wrk -t 8 -c 1000 -d 60s http://localhost:8000/api/products/123/

# 結果:
Running 60s test @ http://localhost:8000/api/products/123/
  8 threads and 1000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   185.32ms   45.23ms   1.50s    89.45%
    Req/Sec     687.23    156.78     1.20k    78.23%

  328,754 requests in 60.00s, 156.32MB read

Requests/sec:   5479.23  ← 超過目標 1000 QPS ✅
Transfer/sec:      2.61MB

分析:

目標:1000 QPS
實際:5479 QPS
超出:5.5 倍

平均延遲:185ms
P95 延遲:250ms
P99 延遲:380ms

資源使用:
CPU:65%
記憶體:8.5GB / 16GB

結論:配置完美滿足需求!✅


⚠️ 常見問題與解決方案

問題 1:外部 API 超時導致請求失敗

症狀:

[ERROR] Worker timeout (pid:12345)
[ERROR] WORKER TIMEOUT (pid:12346)

原因:

  • 外部 API 響應太慢(> timeout 設定)
  • Worker 被 Gunicorn 誤殺

解決方案:

# 方案 1:增加 Gunicorn timeout
timeout = 180  # 從 120 增加到 180

# 方案 2:為外部請求設定獨立的 timeout(推薦)
async with httpx.AsyncClient(timeout=10.0) as client:  # 10 秒超時
    try:
        resp = await client.get(external_url)
    except httpx.TimeoutException:
        # 優雅處理超時
        return default_value

# 方案 3:使用降級策略
async def fetch_with_fallback(url, fallback_value):
    try:
        async with httpx.AsyncClient(timeout=5.0) as client:
            resp = await client.get(url)
            return resp.json()
    except Exception as e:
        logger.warning(f"API call failed: {e}, using fallback")
        return fallback_value

問題 2:資料庫連接池耗盡

症狀:

django.db.utils.OperationalError: FATAL: sorry, too many clients already

原因:

Workers × 每個 Worker 的連接數 > 資料庫最大連接數

例如:
8 workers × 100 connections = 800 connections
但 PostgreSQL max_connections = 200

結果:連接池耗盡!

解決方案:

# settings.py

# 方案 1:配置合理的連接池大小
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydb',
        'CONN_MAX_AGE': 600,  # 持久連接
        # 計算:200 max_connections / 8 workers = 25 per worker
        'OPTIONS': {
            'connect_timeout': 10,
        }
    }
}

# 方案 2:使用連接池中間件(推薦)
# pip install django-db-connection-pool

DATABASES = {
    'default': {
        'ENGINE': 'dj_db_conn_pool.backends.postgresql',
        'POOL_OPTIONS': {
            'POOL_SIZE': 10,  # 每個 worker 最多 10 個連接
            'MAX_OVERFLOW': 5,
        }
    }
}

# 總連接數:8 workers × 10 = 80(安全範圍內)

# 方案 3:在 post_fork Hook 中配置
def post_fork(server, worker):
    from django import db
    from django.db.backends.postgresql.base import DatabaseWrapper

    # 關閉繼承的連接
    db.connections.close_all()

    # 為每個 worker 設定連接限制
    for conn in db.connections.all():
        conn.settings_dict['CONN_MAX_AGE'] = 300

問題 3:Redis 連接過多

症狀:

redis.exceptions.ConnectionError: Error 111 connecting to localhost:6379.
Connection refused.

解決方案:

# settings.py

# 使用連接池
CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/1',
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
            'CONNECTION_POOL_KWARGS': {
                'max_connections': 50,  # 每個進程最多 50 連接
                'retry_on_timeout': True,
            },
            'SOCKET_CONNECT_TIMEOUT': 5,
            'SOCKET_TIMEOUT': 5,
        }
    }
}

# 計算:8 workers × 50 = 400 connections
# 確保 Redis maxclients 設定夠大(預設 10000)

問題 4:記憶體使用持續增長

症狀:

# 記憶體使用不斷增長
ps aux | grep gunicorn
# Worker 記憶體從 200MB 增長到 1GB+

原因:

  • 應用程式記憶體洩漏
  • Worker 長時間運行累積垃圾

解決方案:

# gunicorn.conf.py

# 方案 1:定期重啟 workers
max_requests = 2000  # 處理 2000 請求後重啟
max_requests_jitter = 200  # 加入隨機性避免同時重啟

# 方案 2:記憶體限制重啟
import psutil

def pre_request(worker, req):
    """每個請求前檢查記憶體"""
    process = psutil.Process(worker.pid)
    mem_mb = process.memory_info().rss / 1024 / 1024

    # 如果 worker 記憶體超過 500MB,標記重啟
    if mem_mb > 500:
        worker.log.warning(f"Worker {worker.pid} memory: {mem_mb}MB, will restart soon")
        # 可以設定 worker.alive = False 強制重啟

# 方案 3:使用垃圾回收
def post_request(worker, req, environ, resp):
    """每 100 個請求手動觸發 GC"""
    import gc
    if not hasattr(worker, 'request_count'):
        worker.request_count = 0

    worker.request_count += 1
    if worker.request_count % 100 == 0:
        gc.collect()

💡 面試常見問題

Q1:什麼是 I/O 密集型應用?為什麼要用異步?

完整答案:

I/O 密集型應用是指大部分時間在等待外部資源(資料庫、API、文件讀寫)而不是 CPU 計算的應用。

典型場景:

  • API 網關:調用多個外部服務
  • 微服務:整合多個數據源
  • Web 應用:大量資料庫查詢

為什麼用異步?

同步模型的問題:

# Sync Worker: 一次只能處理一個請求
請求 A: [等待 DB 500ms]  Worker 閒置
請求 B: 等待 Worker A 完成...

結果Worker 大部分時間在等待浪費資源

異步模型的優勢:

# Async Worker: 等待時可處理其他請求
請求 A: [發起 DB 查詢]  等待中
請求 B: [發起 API 調用]  等待中
請求 C: [發起 Redis 讀取]  等待中

Worker 在三個請求的等待間切換充分利用時間
結果一個 Worker 可同時處理數百個請求

性能對比:

  • Sync Worker: 9 個 workers,100 QPS
  • Async Worker: 4 個 workers,1000+ QPS
  • 提升 10 倍以上!

Q2:ASGI 和 Gevent 都是異步,有什麼區別?

完整答案:

雖然都能處理並發,但實現原理和性能差異很大:

特性ASGI (Uvicorn)Gevent
技術基礎Python 原生 asyncioGreenlet 協程
語法async/await(標準語法)同步語法(猴子補丁)
性能更快(原生事件循環)稍慢(協程切換開銷)
兼容性需要異步庫自動 patch 標準庫
維護性官方支援(Django 3.0+)社群維護
推薦場景✅ 新專案首選⚠️ 遺留系統維護

ASGI 範例:

async def view(request):
    data = await fetch_data()  # 原生 async/await
    return JsonResponse(data)

Gevent 範例:

from gevent import monkey
monkey.patch_all()  # 猴子補丁,改變標準庫行為

def view(request):
    data = fetch_data()  # 看起來是同步,實際被 patch 成異步
    return JsonResponse(data)

結論:新專案用 ASGI,性能更好,維護性更強。


Q3:如何判斷應用是否為 I/O 密集型?

完整答案:

有幾個方法可以判斷:

方法 1:分析代碼

# 計算 I/O 操作占比

I/O 操作
 資料庫查詢 (ORM)
 Cache 讀寫 (Redis)
 外部 API 調用 (httpx/requests)
 文件讀寫 (open/read/write)
 消息隊列 (RabbitMQ/Kafka)

CPU 操作
 迴圈計算
 數據處理
 加密解密
 圖片處理

如果 I/O 操作 > 60%就是 I/O 密集型

方法 2:性能分析工具

# 使用 django-debug-toolbar
# 查看 SQL 查詢時間

# 或使用 cProfile
python -m cProfile -o profile.stats manage.py runserver

# 分析結果
import pstats
p = pstats.Stats('profile.stats')
p.sort_stats('cumulative').print_stats(20)

# 如果 I/O 函數(query, fetch, read)佔用時間最多
# → I/O 密集型

方法 3:監控伺服器指標

# 運行應用後觀察
top

# 如果:
# - CPU 使用率 < 50%
# - I/O wait (wa) > 20%
# → I/O 密集型

# 如果:
# - CPU 使用率 > 80%
# - I/O wait < 10%
# → CPU 密集型

快速判斷標準:

  • 平均響應時間 > 100ms → 很可能是 I/O 密集型
  • 主要操作是查詢/調用 → I/O 密集型
  • 主要操作是計算/處理 → CPU 密集型

Q4:I/O 密集型應用如何優化性能?

完整答案:

優化策略分為四個層次:

1. Worker 配置優化

# 使用 ASGI 異步 Worker
worker_class = "uvicorn.workers.UvicornWorker"
workers = CPU_cores  # 不需要太多
worker_connections = 1000  # 每個 worker 的並發數

2. 代碼層優化

# 使用異步代碼
async def view(request):
    # 並發執行多個 I/O 操作
    task1 = fetch_data_from_db()
    task2 = call_external_api()
    task3 = read_from_cache()

    result1, result2, result3 = await asyncio.gather(
        task1, task2, task3
    )

3. 資料庫優化

# select_related 減少查詢次數
orders = Order.objects.select_related('user', 'product').all()

# 使用索引
class User(models.Model):
    email = models.EmailField(db_index=True)

# 使用連接池
DATABASES = {
    'default': {
        'ENGINE': 'dj_db_conn_pool.backends.postgresql',
        'POOL_OPTIONS': {'POOL_SIZE': 10}
    }
}

4. 緩存策略

# 使用 Redis 緩存熱數據
from django.core.cache import cache

def get_user_data(user_id):
    cache_key = f'user:{user_id}'
    data = cache.get(cache_key)
    if data is None:
        data = fetch_from_db(user_id)
        cache.set(cache_key, data, timeout=300)
    return data

優化優先級:

  1. Worker 配置(WSGI → ASGI):10x 提升 ⭐⭐⭐
  2. 添加緩存:2-5x 提升 ⭐⭐⭐
  3. 資料庫優化:2-3x 提升 ⭐⭐
  4. 代碼重構(使用異步):1.5-2x 提升 ⭐

✅ 重點回顧

I/O 密集型應用特徵

✓ 大量外部調用(DB、API、Cache)
✓ 響應時間主要花在等待
✓ CPU 使用率 < 50%
✓ I/O wait > 20%

最佳配置

# 推薦配置(Django 3.0+)
workers = multiprocessing.cpu_count()
worker_class = "uvicorn.workers.UvicornWorker"
timeout = 120
keepalive = 20

性能提升

Sync Worker → Async Worker
性能提升:10-35 倍
Workers 需求:減少 50%

優化策略

1. Worker 配置:使用 ASGI
2. 代碼優化:使用 async/await
3. 資料庫優化:連接池、索引、查詢優化
4. 緩存策略:Redis 緩存熱數據

📚 接下來

下一篇:03-2. 案例:CPU 密集型應用

  • 影像處理、數據分析
  • 如何配置 CPU 密集型應用
  • 與 I/O 密集型的對比

相關章節:


最後更新:2025-10-31

0%