logo托特 | 部落格

如何製作一個類似 Facebook Messenger 的聊天平台

Huaying Tsai
Huaying Tsai
2020年6月2日

為了方便平台上用戶們相互聯繫,製作了一個基礎聊天軟體,本篇主要討論的會是架構面及功能上的一些細節。

關於架構

大部分的形況下網站運行的方式只涉及到單向的資料傳遞,不管是直接 請求頁面、或是 ajax 做 get/post/delete… 操作,都是 client 端向 server 提出請求。

如果今天需要做實時的應用像是聊天功能或是通知功能,我們需要 server 能主動通知 client 端。在這情況下最常用的有兩種 — PollingWebSocket

Polling

Polling 顧名思義就是由 client 端持續地的向 server 端發送請求直到有結果為止,很適合在執行時間稍長的任務使用。舉例來說,假設你今天有個問卷網站,可以一次寄 email 邀請五十個人。邀請按鈕點下以後可能需要一分鐘去處理這麼多人的邀請信件寄送,你的網站又想要在任務開始後實時追蹤發信的進度,這情況下 Polling 就是個很適合的策略。 但持續性的向 server 發送請求很消耗支援,因此我們可以用一些方式來減緩資源消耗。常見的像是 exponential backoff , 就是當你當下還拿不到結果或是結果跟前一次一樣,那你就再加長你的 delay 時間。一開始可能每 delay 100ms 送一次請求,之後的每一次請求如果還拿不到結果就把 delay time * 2 直到 timeout。

但以上方法並不適合實時應用。以聊天應用的情況來說,我們得持續的做 polling 向 server 要新的信息,非常消耗資源,但用了 exponetial backoff 又會導致資料更新不及時,所以又有一種方案:Long Polling

1_wYm1xTldsKwXqXnQATdIqA

Long polling 的概念一樣是不斷的發送請求到 server,但 server 會握著你的請求不放,直到有資料可以回傳或是 timeout。當每次的請求有結果後,client 又會建立新的請求以達到持續連線的效果。這樣的做法就不向一般的 Polling 這麼消耗資源,也保有了資料的即時性。印象中 Facebook 有篇文章寫說他們如何採用 Long Polling 來實現 chat 還是 notification 的功能,有興趣的人能在網上搜一下。

WebSocket

WebSocket 屏除了 http 的協定,不再是一個 request 與一個response 的方式。它的網址為 ws:// 或是 wss:// 開頭,概念就是事先在 client 端與 server 之間建立一個通道,資料可以進行雙向交互,這樣的設計也符合實時應用的需要。

我們的平台用的是 Graphql 的 Subscription,底層就是用 WebSocket 所實現的。

1_b8ObzSIVOTov_Lu19kdZEQ

關於功能

功能上我們需要的是簡單的一個朋友列表以及對話欄。 後端資料方面的設計不複雜,比較繁瑣的就是當新訊息進來的時候,除了增加一筆新的 Message 資料外,還要送 data 到相對應的 client 更新朋友列表的已讀狀態與最後則訊息的資料欄。

1_xMctyfxiv2NJjq39My5xiw

前端部分相對複雜許多,要考慮的地方像是 Pagination、設定訊息已讀、相近時間訊息的聚合,以及 Scroll 上面的問題等等。

設定訊息已讀的部分,比較 tricky 的點是在收到新訊息的時候,假如你已經在這的對話的頁面,你必須立刻再發個 request 告訴 server 設定已讀,並且前端不能亮小紅點。

時間聚合的點要考慮的是,多近時間內的訊息你要把它聚集在一起?還有不同時間點的時間要如何顯示?比如越近的時間顯示時分,稍遠一點顯示星期幾,再遠點顯示日期之類的。

Scroll 的部分則是需要分辨什麼時候需要自動的 scroll to bottom 什麼時候不需要。 Style 方面則是 Responsive 的部分還有手機瀏覽器的特殊處理,這種輸入欄至底、高度 fixed 的 layout 很容易在手機上有奇怪的行為。

結論

實際實作起來會比說起來的複雜要多,聊天功能牽扯到實時數據更新,比一般的 Web App 要花更多時間,但能實時交流的功能用起來也比較有趣! 最後歡迎試用以及提供意見,第一版可能會有一些沒考慮周全的地方,有問題請聯絡 support@thoth.tw :)

1_Vy-8DWhDSzSwNDZaQ5Ve5A

# 平台故事
聯絡我們 support@thoth.tw
托特部落格FacebookInstagram
隱私權政策
© 2021 托特 thoth
隱私權政策
© 2021 托特 thoth