簡介 – Django Channels:為 Django 提供異步通信與長連接協議支持

A. Django Channels是什麼

Django Channels 擴展 Django 的功能,使其具備以下特性:

  • 異步支持與協議擴展:Django Channels 擴展了 Django 的能力,不僅支持異步視圖,還支持多種長連接協議,如 WebSockets 和 MQTT,適合需要持久連接的應用場景。
  • 保留同步特性:開發者可選擇使用傳統同步風格、完全異步或兩者結合的方式來編寫代碼,方便根據需求進行適當的技術選擇。
  • 與 Django 集成:與 Django 的認證系統、會話系統等功能無縫集成,簡化將只支持 HTTP 的項目擴展到其他協議的過程。
  • 事件驅動架構:提供通道層(channel layers),支持進程間通信和應用模塊化部署,提高項目可擴展性和運行效率。
  • 提高可擴展性與性能:能夠有效應對大量併發連接,提升應用性能和響應能力,方便構建複雜的後端服務。

Channels 允許使用傳統 Django view,同時可以與自定義 HTTP 長輪詢(long-polling)或 WebSocket 接收器共存,以便處理同步與異步的工作需求,實現靈活的開發體驗。

B. WSGI vs. ASGI

WSGI(Web Server Gateway Interface)和 ASGI(Asynchronous Server Gateway Interface)在以下幾個主要方面有所不同:

  1. 同步 vs. 異步

    • WSGI:僅支持同步編程模型。這意味著每個請求在處理過程中會持有一個線程或進程,並在回應返回前一直占用資源,這在需要長連接或高併發的情境下效率不高。
    • ASGI:支持異步編程模型,允許處理多個請求或事件而不需要為每個事件專門分配一個線程或進程。這樣可以更有效地管理資源,尤其是在高併發或需要持續連接的應用中,如 WebSockets。
  2. 協議支持

    • WSGI:專注於 HTTP 協議,無法天然支持 WebSockets 或其他需要持續連接的協議。
    • ASGI:設計為支持多種協議,包括 HTTP、WebSockets、MQTT 等,這使其適合現代實時和多樣化的網絡應用。
  3. 資源效率

    • WSGI:由於同步處理,每個連接需要一個獨立的線程,這可能導致高併發時資源的迅速耗盡。
    • ASGI:異步處理使得同一資源可以被多個事件共享,降低了高併發下的資源消耗,提高了系統的可伸縮性。
  4. 應用場景

    • WSGI:適用於傳統的同步 web 應用程序,如主要需要頁面渲染的情況。
    • ASGI:更適合需要實時互動、數據流處理或其他異步需求的應用,如聊天應用、在線遊戲或物聯網設備通信。

在 Django Channels 和 ASGI 中,連接被分為「範疇」(scope)和一系列的「事件」(events):

  • Scope 是描述單一連接的細節,包括請求的路徑和使用者資訊,並隨著連接的存活時間而保持持續。
  • Events 則是用戶互動的具體表現,例如 HTTP 請求或 WebSocket 傳輸。

對於 HTTP,Scope 持續一個請求,而對於 WebSocket,它存活於整個連接期間。

Channels 提供 consumers 來簡化這一處理過程,使你更容易實現應用程式的即時互動功能。

C. Consumer

Django Channels 的 Consumer 是用來處理事件的基本單位,它負責消費來自不同協議的事件。當有新的請求或連接進來時,Channels 根據路由表選擇並啟動相應的 Consumer。Consumer 可以長期運行以持續處理長連接協議(如 WebSockets),或者短期運行來處理 HTTP 請求。它們以事件的方式運行,可以選擇同步執行或完全異步執行,提供高效的併發處理能力。

D. Routing and Multiple Protocols

Django Channels 可以讓你將多個 consumer(這些 consumer 本身就是 ASGI Application)組合成一個更大的應用來代表你的項目,這可以通過路由來實現:

application = URLRouter([
    path("chat/admin/", AdminChatConsumer.as_asgi()),
    path("chat/", PublicChatConsumer.as_asgi()),
])

Channels 不僅僅是為了 HTTP 和 WebSockets 建立的,它還允許你將任何協議整合到 Django 環境中。這是通過構建一個伺服器來實現的,該伺服器會將這些協議映射到一組類似的事件中。例如,你可以以下面的方式構建一個聊天機器人:

class ChattyBotConsumer(SyncConsumer):
    def telegram_message(self, message):
        """任何聊天中的簡單回音處理."""
        self.send({
            "type": "telegram.message",
            "text": "You said: %s" % message["text"],
        })

然後使用另一個路由器讓一個項目同時支持 WebSockets 和聊天請求:

application = ProtocolTypeRouter({
    "websocket": URLRouter([
        path("chat/admin/", AdminChatConsumer.as_asgi()),
        path("chat/", PublicChatConsumer.as_asgi()),
    ]),
    "telegram": ChattyBotConsumer.as_asgi(),
})

E. Cross-Process Communication

隨著應用系統的複雜性增加,開發者往往需要在不同的應用實例之間進行通信。比如,在一個聊天室應用中,當一個實例接收到新消息時,需要將該消息分發給代表聊天房中其他成員的實例。為此,Django Channels 提供了通道層(Channel layer)的概念。通道層是一種底層抽象,圍繞著一組傳輸方案,允許不同的進程之間進行信息交換。每個應用實例都有一個唯一的通道名稱,並且可以加入組(Groups),這樣就可以實現點對點和廣播形式的消息傳遞。

通過使用通道層,開發者可以更高效地實現應用間的實時通信,而不需要頻繁查詢資料庫,從而降低系統的負擔,提高消息傳遞的速度與效率。這對於需要動態更新或高水平交互的應用(如即時聊天、協同編輯等)尤為重要。Django Channels 的這個功能使得開發者能夠更加輕鬆地構建高性能的網絡應用。

F. 總結

Django Channels 是擴展 Django 的一個框架,它增加了非同步支持和長連接協議支持,包括 WebSockets 和 MQTT,適合需要持久連接的應用場景。相對於WSGI,ASGI 支持非同步處理和多協議,提升資源效率和系統擴展性。Django Channels 透過 Channel Layer 這一種底層的抽象,用於支持進程間的消息交換,適合動態更新或高交互的應用場景。

這篇文章是Django Channels的簡介,後續會有其他文章介紹具體的使用方式,及相關內容。

G. 系列文章