Discord 風格聊天應用
模仿 Discord 架構的即時聊天應用,支援伺服器、頻道、私訊與好友系統,前後端採 Vue 3 + Go 開發,後端現已支援 K3s 水平擴展與 Redis Pub/Sub 跨 Pod 廣播。

專案概述
以 Discord 為樣板製作的即時聊天應用,包含前端(Vue 3)和後端(Go)兩個部分。支援伺服器(Guild)、頻道(Channel)、私訊(DM)、好友系統、檔案上傳與 WebSocket 即時訊息。專案初版以單實例 WebSocket Hub 為核心,後續逐步演進為可部署於 K3s 的即時系統:透過 Redis Pub/Sub 將 room 事件跨 Pod 傳播,讓多個 chat-app 實例在水平擴展後仍能維持一致的即時推播體驗;同時搭配 MongoDB、Redis、Prometheus、pprof、k6 與 ArgoCD/GitOps,將聊天室從功能實作推進到接近生產環境的部署與驗證模式。
技術挑戰與解決方案
從單實例 WebSocket 演進到跨 Pod 廣播
原本的聊天室即時層以單程序記憶體內的 Room / Client 結構為核心,當服務部署到多個 Pod 時,訊息只會送到連線所在的單一實例,無法跨 Pod 廣播。
JWT 驗證與安全性
需要為 SPA 實作安全的無狀態認證系統,同時在多 Pod 部署下仍維持登入、刷新與撤銷流程一致。
K3s 部署與水平擴展驗證
Docker Compose 可以跑起來,但無法驗證真實的多副本負載均衡、Probe、滾動更新與資源擴縮行為。
檔案儲存與無狀態 Pod 限制
聊天應用需要頭像、伺服器圖片等檔案上傳,但 K3s Pod 是無狀態的,本地 uploads 目錄在重建或擴容後可能遺失或不一致。
可觀測性與擴展行為驗證
水平擴展後如果沒有指標與壓測資料,很難判斷瓶頸究竟在 WebSocket、Redis、MongoDB 還是 Pod 資源配額。
系統架構
前端:Vue 3 + TypeScript + Pinia + Element Plus。後端:Go 1.25 + Gin + gorilla/websocket,維持 Controller → Service → Repository 三層架構與手寫依賴注入。即時層以 RoomManager 管理房間與本機 Client,MessageHandler 在訊息入庫後透過 Redis Publish 發送到 room:<type>:<id> channel,各 Pod 在 InitRoom 時訂閱對應 channel,收到事件後只轉發給本機 WebSocket 連線,解決水平擴展後的跨實例廣播問題。部署層使用 K3s、Deployment、HPA、Kustomize 與 ArgoCD 管理多 Pod 環境,並以 Prometheus、pprof 和 k6 觀察效能與擴展行為。
學習與心得
這個專案讓我從單機即時聊天應用,往真正可擴展的即時系統多走了一步。我不只學會 Go 後端、JWT 與 WebSocket 連線管理,也實際面對了水平擴展後最麻煩的狀態同步問題:當 WebSocket 連線分散到多個 Pod,訊息就不能只靠記憶體廣播。我透過 Redis Pub/Sub、K3s/HPA 與壓測驗證,理解了即時系統在多實例環境中的資料流、無狀態部署限制,以及部署、監控與負載測試必須一起設計。