前端系统设计 - 设计聊天系统 (Chat System)
2024年4月1日
本篇详细解说本收录在 E+ 的前端系统设计专题
设计聊天系统 (Chat System) 很普遍,非常多公司都有做,也是系统设计面试很经典的问题。这边我们会列下设计聊天应用的前端,应该要考量什么面向,协助大家在准备面试时,知道要往哪些方向思考。
如果你想看每个思考面向,我们会如何回答,可以在 E+ 的《前端系统设计 - 设计聊天系统 (Chat System)》一文读到。
先厘清需求
不论在面试,或者在工作时,当听到要设计一个聊天系统,一定要先厘清需求。假如面试官问你,或者工作时 PM 跟你提说要设计聊天系统,你会有哪些想厘清的问题呢? 在往下读之前,不妨自己先想一想。
在思考这问题时,推荐可以先回到使用者的角度,平常大家有用的不论是跟朋友家人用的 Line,或者 Instagram 中的聊天,又或者 Discord,这些都是聊天系统的范畴。可以想看看,这些不同聊天系统,分别有哪些不同,可以从这些差异去想要厘清的问题。
关于聊天系统,以下的问题是推荐要厘清的:
- 这个聊天系统的目标用户是谁? 上面提的 Line、Instagram、Discord 目标族群很不同,都是聊天系统,但设计上会有差异
- 最基本的功能涵盖什么? 收发讯息外,需要有历史记录吗? 要有聊天对象列表吗?
- 收发的讯息类型是纯文字的吗? 还是要支援不同多媒体? 例如图片、语音、影片等
- 聊天是即时的吗? 还是非即时的聊天?
- 聊天都是 1 对 1 的吗? 需要有群组聊天功能吗?
- 要支援离线 (offline) 功能吗?
除了上面这些,还有细部可以问的,包含:
- 要有通知的功能吗?
- 要有对方正在输入讯息的功能吗? (例如 Discord 可以看到别人正在打字中)
- 要有按表情符号的功能吗? (例如 Discord 每个讯息都可以按表情符号)
- 要支援收回讯息吗?
- 要支援国际化 (i18n) 吗?
从架构的角度看的技术讨论
我们先从最基本的 1 对 1 聊天,要支援聊天对象列表、历史讯息,要是即时聊天,仅需用纯文字,同时要支援离线功能。当看到上面这些功能,大家会如何设计前端呢?
聊天讯息要包含哪些状态?
对前端来说,状态管理往往是挑战之一。对于 1 对 1 聊天,第一个要思考的是聊天讯息的状态。以常见的聊天应用,该包含哪些状态? 为什么要有这些? 这部分如果设计的好,对功能开发也会比较容易照顾不同面向。
渲染方式选择,要选 CSR 或 SSR?
对于前端来说,不同种类的应用,会分别适合不同类的渲染方式。假如今天被问说聊天应用该选哪一种,你会如何回答呢? 回答这问题前,可以先思考,CSR 与 SSR 分别适用的情境。在思考哪个特性比较适合聊天应用。
离线支援选哪种存储方案?
现在有许多聊天应用都有支援离线,换句话说,今天即使网路突然断线,也可以点其他聊天对象,去看先前聊天过的历史讯息,此外也可以发送讯息 (但要等到重新有网路后才会发送)。要做到离线支援,可以分两块来讨论。第一块是假如用户离线后重新整理,要如何确保有 HTML、CSS、JavaScript? 你会选择用什么来存呢?
此外,聊天的讯息应该被存在客户端的哪里呢? 谈到前端的存储,多数人第一时间可能会想到 cookie、sessionStorage 以及 localStorage (差别详见此篇)。除此之外,先前我们也有介绍过 IndexedDB。在这些选项中,你会选哪一个呢?
与后端共同制定 API
前端系统设计面试,也常会被问到跟后端共同制定的 API 该如何设计,以聊天应用来说,最基本的需求来说,至少需要以下的 API 来满足:
- 获取聊天对象列表
- 获取历史讯息
- 传送讯息
- 接收讯息
大家可以思考一下,被问到这些接口,你会如何设计呢?
基本追问题
除了上面的讨论面向外,很可能在面试中有以下的追问:
- 追问一:如何在浏览器的多个分页同步
- 追问二:如何实作即时聊天 (该用哪个协定? 为什么?)
- 追问三:效能优化可以从哪些面向切入
延伸问题
以下列出几个在面试中常见的延伸问题。推荐大家也可以准备:
- 延伸问题一:支援各种类型对话该如何设计? 例如图片、语音?
- 延伸问题二:表情符号功能要如何设计?
- 延伸问题三:群组聊天该如何设计?
- 延伸问题四:串聊 (Threads) 要如何设计?