網頁應用程式的訊息佇列與背景工作

Backend2026-09-17TryQuickToolBox

為何你的網頁應用程式需要背景工作

當使用者點擊「註冊」或「下單」時,他們期望快速回應。但該點擊觸發的許多操作——發送歡迎電子郵件、產生 PDF 發票、調整上傳圖片大小,或與第三方 API 同步資料——可能需要數秒甚至數分鐘。如果你在請求期間同步執行這些任務,使用者必須等待,而你的伺服器也會佔用資源。背景工作透過將工作移出請求-回應週期來解決這個問題。

訊息佇列是背景工作系統的骨幹。它們讓你的網頁應用程式將工作加入佇列並立即返回回應,而獨立的工作者程序則取出工作並以非同步方式執行。這將網頁層與處理層解耦,提升回應性、可靠性與可擴展性。

核心概念:佇列、生產者與消費者

最簡單來說,訊息佇列是一個緩衝區,用於保存訊息直到消費者取出它們。其組成部分包括:

此模式通常稱為生產者-消費者或發布-訂閱(如果多個消費者可以對同一訊息採取行動)。關鍵好處是解耦:生產者不需要知道誰處理工作或需要多長時間。

背景工作的常見使用案例

背景工作非常適合任何不需要在向使用者發送回應之前完成的任務。典型例子包括:

如果一個任務可以延遲幾秒而不損害使用者體驗,它就是背景工作的候選者。

為工作選擇合適的工具

正確的訊息佇列取決於你的規模、可靠性需求與現有技術堆疊。以下是常見選項的比較:

工具 最適合 持久性 複雜度
Redis(搭配 RQ、Bull、Celery) 簡單、快速的佇列;中小規模 選用(可持久化至磁碟) 低
RabbitMQ 複雜路由、保證送達、高可靠性 是 中
Apache Kafka 高吞吐量事件串流、日誌聚合 是 高
AWS SQS 全託管、無伺服器、按用量付費 是 低
資料庫支援(例如 PostgreSQL SKIP LOCKED) 簡單、無需額外基礎設施 是 低

對許多網頁應用程式而言,從 Redis 或資料庫支援的佇列開始就足夠了。隨著規模成長,你可以遷移到更強大的代理,如 RabbitMQ 或 Kafka。

實作背景工作:逐步指南

讓我們使用 Python、Celery 和 Redis 走過基本實作。相同的原則適用於其他技術堆疊(例如 Node.js 搭配 Bull、Ruby 搭配 Sidekiq、Go 搭配 Machinery)。

1. 設定 Redis 與 Celery

安裝 Redis 與 Celery 函式庫。設定 Celery 使用 Redis 作為代理與結果後端。

# Install dependencies
pip install celery redis

# Start Redis server (if not already running)
redis-server

2. 定義 Celery 應用程式

建立一個檔案 tasks.py,初始化 Celery 並定義背景任務。

from celery import Celery

app = Celery('tasks', broker='redis://localhost:6379/0')

@app.task
def send_welcome_email(user_id):
    # Simulate sending an email
    print(f"Sending welcome email to user {user_id}")
    # In production, integrate with an email service
    return f"Email sent to user {user_id}"

3. 從你的網頁應用程式將工作加入佇列

在你的網頁框架中(例如 Flask、Django),以非同步方式呼叫任務。.delay() 方法會將工作加入佇列並立即返回。

from tasks import send_welcome_email

@app.route('/signup', methods=['POST'])
def signup():
    # ... create user in database ...
    send_welcome_email.delay(user_id=123)
    return {"status": "success"}, 202

4. 執行工作者程序

啟動一個或多個工作者程序,監聽佇列並執行任務。

celery -A tasks worker --loglevel=info

現在,當使用者註冊時,網頁應用程式立即返回 202 Accepted 回應,而工作者則在背景發送電子郵件。

可靠背景工作的最佳實務

背景工作會引入新的失敗模式。遵循以下實務讓你的系統保持穩健:

擴展你的背景工作系統

隨著應用程式成長,你需要同時擴展佇列與工作者。策略包括:

請記住,增加工作者會提高並行度,這可能對資料庫或外部 API 造成壓力。監控資源使用情況並相應調整。

常見問題

訊息佇列與背景工作有何不同?

訊息佇列是傳輸訊息的基礎設施,而背景工作是由訊息表示的工作單元。你將工作(訊息)加入佇列,工作者則處理它。

我需要像 RabbitMQ 這樣的獨立訊息代理嗎?

不一定。對許多網頁應用程式而言,Redis 甚至資料庫表格都可以作為簡單的佇列。當你需要進階路由、保證送達或高吞吐量時,才使用專用代理。

如何處理失敗的背景工作?

實作帶指數退避與最大重試次數的重試。之後,將工作移至死信佇列以供手動審查。始終記錄失敗並附上足夠的上下文以便除錯。

準備好優化你的網頁應用程式效能了嗎?從卸載你的第一個背景工作開始。當你在這些工作中需要處理 PDF 或圖片時,請查看我們的 PDF 壓縮工具,在將檔案發送給使用者之前縮小檔案大小。