后端系统设计 - 设计聊天系统 (Chat System)

2024年4月1日

💎 加入 E+ 成長計畫 與超過 350+ 位軟體工程師一同在社群中成長,並且獲得更多的軟體工程學習資源

本篇详细解说本收录在 E+ 的后端系统设计专题

前端系统设计 - 设计聊天系统 (Chat System) 我们从前端的角度来讨论设计聊天系统,在这篇文章,我们将切换到后端的角度,来谈设计聊天系统。

厘清需求

跟前端系统设计一样,如果面试官问你,或者工作时 PM 跟你提说要设计聊天系统,第一个反应要是先去厘清需求。

除了在前端篇提到要厘清的

  • 这个聊天系统的目标用户是谁? 上面提的 Line、Instagram、Discord 目标族群很不同,都是聊天系统,但设计上会有差异
  • 最基本的功能涵盖什么? 收发讯息外,需要有历史记录吗? 要有聊天对象列表吗?
  • 收发的讯息类型是纯文字的吗? 还是要支援不同多媒体? 例如图片、语音、影片等
  • 聊天是即时的吗? 还是非即时的聊天?
  • 聊天都是 1 对 1 的吗? 需要有群组聊天功能吗?

一般从后端的角度还会要厘清

  • 系统预计承载的规模? 讯息要存多久? (要去估算需要多少运算、存储资源)
  • 讯息种类的限制,例如文字的长度限制,或是有影音的话会如何限制?
  • 需不需要处理端到端的讯息加密 (end-to-end encryption)?
  • 要支援多装置吗? (例如同时支援网页、行动端)

架构讨论

跟前端篇一样,先给定我们是处理 1 对 1 聊天,同时先以支援文字聊天为主,接着会再延伸讨论其他会被追问的问题。当想到聊天系统,从最单纯的角度来看,我们会有双边,一边是发送讯息的人,另一边是接收讯息的人,而在两者中间则会是负责处理聊天的服务,服务同时会接到资料库,来确保讯息都能被永久存下来。

这时会要面对我们必须做的第一个技术选择,要让收到讯息的人,能收到从伺服器端发来的讯息,该选什么协定?

第一个是长轮询 (long polling)

所谓的长轮询,是让客户端发送请求,然后保持跟伺服器端的连接,直到伺服器端回应后,才会再发送新的请求。长轮询跟轮询 (polling) 的差别在于,一般的轮询会是固定一段时间,客户端持续发送请求,即使伺服器端没有回应,仍然会持续发送,这会导致许多不必要的浪费。

而长轮询因为会维持着连接,直到拿到回应才会再发送下个请求,相比起来会少掉许多不必要的浪费。但要注意,如果是长时间没有发送讯息,因为连接会有 timeout 的状况,因此仍会有断掉后需要重新连线的浪费问题。

第二个是 Server-sent Event

Server-sent Event 顾名思义,是由伺服器端主动推送到客户端,它是单项式的,对于双向的聊天来说,相对没有这么合适,因为聊天的传讯是双向的。Server-sent Event 一般比较适合在通知系统,这种单向从伺服器传到客户端的情境。

第三个是 WebSocket

WebSocket 是个双向的协定,且具有长连接的特性,对于即时聊天来说,是相当适合的一种协定,目前多数业界的聊天系统也会选择 WebSocket 作为处理即时聊天的部分

当保持着 WebSocket 的连接,客户端可以主动传讯息给伺服器端,伺服器端也可以主动传讯息给客户端。也因为是长连接,WebSocket 少掉需要重新建立连接的步骤,这能同时减轻 auth 部分的服务压力。

本文为 E+ 成长计划的深度内容,截取前三分之一开放免费阅读。欢迎加入 E+ 成长计划阅读完整版本 (点此了解 E+ 的详细介绍)

🧵 如果你想收到最即時的內容更新,可以在 FacebookInstagram 上追蹤我們