当前位置: 首页 > news >正文

从零开始:如何设计一个现代化聊天系统

写在前面: 此博客内容已经同步到我的博客网站,如需要获得更优的阅读体验请前往https://mainjaylai.github.io/Blog/blog/system/chat-system

在当今数字化时代,聊天系统已成为我们日常生活和工作中不可或缺的一部分。从个人交流到团队协作,从客户服务到社交网络,聊天应用程序在各个领域都发挥着重要作用。正因如此,理解并掌握聊天系统的设计原理对于软件工程师来说尤为重要。

该博客将深入探讨聊天系统的设计,涵盖从基础架构到高级功能的各个方面。我们将分析当前市场上流行的聊天应用,研究它们的成功之处,并探讨如何将这些经验应用到我们自己的设计中。

图1呈现了目前市场上最受欢迎的几款聊天应用。这些应用之所以能够脱颖而出,不仅因为它们满足了用户的基本通讯需求,还因为它们在用户体验、功能创新和技术实现上都有独到之处。通过学习这些成功案例,我们可以更好地理解用户需求,把握技术趋势,从而设计出更加优秀的聊天系统。

Maple
图 1

在开始设计聊天系统之前,明确系统的具体需求是至关重要的。聊天应用的多样性意味着它们可以服务于广泛的用途和用户群体,因此在设计过程中,我们需要特别注意以下几点:

  1. 明确目标用户: 是面向普通消费者的即时通讯工具,还是针对企业内部沟通的协作平台?了解目标用户群体有助于确定核心功能和用户界面设计。
  2. 确定主要使用场景: 是以一对一聊天为主,还是以群组交流为重点?不同的使用场景会影响系统的架构设计和功能优先级。
  3. 功能需求分析: 除了基本的文字聊天,是否需要支持语音通话、视频会议、文件传输等功能?每增加一项功能都会影响系统的复杂度和资源需求。
  4. 性能要求: 系统需要支持多少同时在线用户?消息传递的延迟要求是什么?这些因素会直接影响到系统的架构设计和技术选型。
  5. 安全性和隐私考虑: 是否需要端到端加密?如何保护用户数据?在某些应用场景中,这可能是最关键的需求之一。
  6. 可扩展性: 系统是否需要能够快速扩展以适应用户增长?这将影响到底层架构的设计。
  7. 跨平台支持: 是否需要支持多种设备和操作系统?这会影响到客户端的开发策略。
  8. 集成需求: 是否需要与其他系统或服务集成?例如,与社交媒体平台或企业管理系统的集成。

好的系统设计始于对需求的深入理解。在实际工作中,这个阶段可能需要多次迭代和讨论。通过仔细分析和明确需求,我们可以为接下来的设计过程奠定坚实的基础,最终交付一个既满足用户需求又技术先进的聊天系统。

第一步 - 理解问题并确立设计范围

确定要设计的聊天应用类型至关重要。市场上有各种类型的聊天应用,如专注于一对一聊天的Facebook Messenger、微信和WhatsApp,侧重群聊的办公应用Slack,以及注重大群交互和低延迟语音聊天的游戏聊天应用Discord。

在该博客中,我们专注于设计一个类似Facebook Messenger的聊天应用,重点关注以下功能:

  • 低延迟的一对一聊天
  • 小型群聊(最多100人)
  • 在线状态显示
  • 多设备支持。同一账户可以同时登录多个设备。
  • 推送通知

确定设计规模也很重要。我们将设计一个支持5000万日活跃用户的系统。这些需求为我们的设计提供了清晰的框架和边界。通过明确这些关键点,我们可以更有针对性地进行系统设计,避免在不必要的功能上浪费时间,同时确保能够满足核心需求和性能指标。

在实际的系统设计中,这个阶段的重要性往往被低估。然而,正是这个阶段的深入讨论和明确定义,为后续的架构设计和技术选型奠定了基础。它不仅有助于我们集中精力于最关键的功能,还能帮助我们预见可能遇到的挑战和瓶颈。例如,知道系统需要支持5000万日活跃用户,我们就可以开始考虑如何设计一个高度可扩展的架构。了解到需要支持多设备登录,我们就需要考虑如何同步不同设备间的消息和状态。而"永久存储聊天历史"这一需求则提醒我们需要设计一个高效的数据存储和检索系统。

通过这个过程,我们不仅明确了设计目标,还初步勾勒出了系统的轮廓。这为接下来的详细设计和技术讨论提供了明确的方向,使我们能够更有效地进行后续的设计工作。

第二步 - 提出高层设计并获得认可

要开发高质量的设计,我们应该对客户端和服务器如何通信有基本的了解。在聊天系统中,客户端可以是移动应用或网页应用。客户端之间不直接通信,而是每个客户端连接到一个支持上述所有功能的聊天服务。让我们专注于基本操作。聊天服务必须支持以下功能:

  • 接收来自其他客户端的消息。
  • 为每条消息找到正确的接收者并将消息转发给接收者。
  • 如果接收者不在线,则在服务器上保留该接收者的消息,直到他们上线。

图2展示了客户端(发送者和接收者)与聊天服务之间的关系。

Maple
图 2

当客户端打算开始聊天时,它使用一个或多个网络协议连接聊天服务。对于聊天服务来说,网络协议的选择很重要。

对于大多数客户端/服务器应用程序,请求是由客户端发起的。这对聊天应用的发送方也是如此。在图2中,当发送者通过聊天服务向接收者发送消息时,它使用经过时间考验的HTTP协议,这是最常见的网络协议。在这种情况下,客户端与聊天服务建立HTTP连接并发送消息,通知服务将消息发送给接收者。这里使用keep-alive很有效,因为keep-alive头允许客户端与聊天服务保持持久连接,同时也减少了TCP握手的次数。HTTP在发送方是一个不错的选择,许多流行的聊天应用,如Facebook,最初就使用HTTP发送消息。

然而,接收方的情况稍微复杂一些。由于HTTP是客户端发起的,从服务器发送消息并不简单。多年来,许多技术被用来模拟服务器发起的连接:轮询(polling)、长轮询(long polling)和WebSocket。这些都是系统设计面试中广泛使用的重要技术,让我们逐一研究。

轮询(Polling)

如图3所示,轮询是一种客户端定期询问服务器是否有可用消息的技术。根据轮询频率的不同,轮询可能会消耗大量资源。它可能会消耗宝贵的服务器资源来回答一个大多数时候答案都是"否"的问题。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
图 3

  1. 工作原理
    • 客户端以固定的时间间隔向服务器发送HTTP请求。
    • 服务器立即响应,无论是否有新的消息可用。
    • 如果有新消息,服务器会在响应中包含这些消息。
    • 如果没有新消息,服务器会发送一个空响应。
  2. 优点
    • 实现简单:客户端和服务器端的逻辑都相对直接。
    • 兼容性好:几乎所有的浏览器和服务器都支持这种方式。
    • 防火墙友好:使用标准的HTTP请求,不会被防火墙阻挡。
  3. 缺点
    • 资源浪费:即使没有新消息,也会频繁发送请求,浪费带宽和服务器资源。
    • 实时性差:消息的接收存在延迟,取决于轮询间隔。
    • 服务器负载高:当有大量客户端同时轮询时,可能会给服务器带来巨大压力。
  4. 优化策略
    • 自适应轮询间隔:根据消息频率动态调整轮询间隔。
    • 批量获取消息:每次轮询获取多条消息,减少请求次数。
    • 结合其他技术:例如,可以用轮询来检查是否有新消息,有的话再建立更高效的连接获取消息内容。

在设计聊天系统时,轮询可能会作为一种降级策略或备用方案使用,例如当WebSocket连接失败时。但对于主要的消息传递机制,我们通常会选择更高效的方法,如WebSocket或长轮询。

长轮询(Long Polling)

由于轮询可能效率低下,下一个进展是长轮询(如图4所示)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
图 4

在长轮询中,客户端保持连接打开,直到实际有新消息可用或达到超时阈值。一旦客户端接收到新消息,它立即向服务器发送另一个请求,重新启动这个过程。长轮询有几个缺点:

  • 发送者和接收者可能不会连接到同一个聊天服务器。基于HTTP的服务器通常是无状态的。如果您使用轮询(Round Robin)进行负载均衡,接收消息的服务器可能与接收消息的客户端没有长轮询连接。
  • 服务器没有好的方法来判断客户端是否已断开连接。
  • 它是低效的。如果用户不经常聊天,长轮询仍会在超时后定期建立连接。
  1. 工作原理
    • 客户端向服务器发送HTTP请求。
    • 如果服务器没有可用的新数据,不会立即发送响应,而是保持请求打开。
    • 当新数据可用时,服务器立即响应该请求。
    • 客户端收到响应后,立即发送新的请求,重新开始这个

相关文章:

从零开始:如何设计一个现代化聊天系统

写在前面: 此博客内容已经同步到我的博客网站,如需要获得更优的阅读体验请前往https://mainjaylai.github.io/Blog/blog/system/chat-system 在当今数字化时代,聊天系统已成为我们日常生活和工作中不可或缺的一部分。从个人交流到团队协作,从客户服务到社交网络,聊天应用…...

香橙派OrangePi AIpro初体验:当小白拿到一块开发板第一时间会做什么?

文章目录 香橙派OrangePi AIpro初体验:当小白拿到一块高性能AI开发板第一时间会做什么前言一、香橙派OrangePi AIpro概述1.简介2.引脚图开箱图片 二、使用体验1.基础操作2.软件工具分析 三、香橙派OrangePi AIpro.测试Demo1.测试Demo1:录音和播音(USB接口…...

【C语言内存函数】

目录 1.memcpy 使用 模拟实现 2.memmove 使用 模拟实现 3.memset 使用 4.memcmp 使用 1.memcpy 使用 void * memcpy ( void * destination, const void * source, size_t num );目的地址 源地址 字节数 destination:指向要复制内…...

Mysql部署MHA高可用

部署前准备: mysql-8.0.27下载地址:https://cdn.mysql.com//Downloads/MySQL-8.0/mysql-8.0.27-1.el7.x86_64.rpm-bundle.tar mha-manager下载地址:https://github.com/yoshinorim/mha4mysql-manager/releases/download/v0.58/mha4mysql-mana…...

【算法学习】射线法判断点在多边形内外(C#)以及确定内外两点连线与边界的交点

1.前言: 在GIS开发中,经常会遇到确定一个坐标点是否在一块区域的内部这一问题。 如果这个问题不是一个单纯的数学问题,例如:在判断DEM、二维图像像素点、3D点云点等含有自身特征信息的这些点是否在一个区域范围内部的时候&#x…...

SQL语句(DML)

DML英文全称是Data Manipulation Language(数据操作语言),用来对数据库中表的数据记录进行增删改等操作 DML-添加数据 insert into employee(id, workno, name, gender, age, idcard) values (1,1,Itcast,男,10,123456789012345678);select *…...

uniapp小程序打开地图导航

uniapp uni.getLocation({type: gcj02, //返回可以用于uni.openLocation的经纬度success: function (res) {const latitude res.latitude;const longitude res.longitude;uni.openLocation({latitude: latitude,longitude: longitude,success: function () {console.log(suc…...

webstorm格式化或保存时 vue3引入的组件被删除了

解决办法 保存时设置 格式化设置...

Java时间转换

一、线程不安全 Date date new Date(); SimpleDateFormat dateFormat new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String prefix dateFormat.format(date);二、线程安全,建议使用 String t1 LocalDateTime.now().format(DateTimeFormatter.ofPattern("y…...

Spring Boot与WebFlux的实战案例

Spring Boot与WebFlux的实战案例 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天,我们将探讨如何利用Spring Boot和WebFlux构建响应式应用的实战…...

vue3引入本地静态资源图片

一、单张图片引入 import imgXX from /assets/images/xx.png二、多张图片引入 说明:import.meta.url 是一个 ESM 的原生功能,会暴露当前模块的 URL。将它与原生的 URL 构造器 组合使用 注意:填写自己项目图片存放的路径 /** vite的特殊性…...

git 禁止dev合并到任何其他分支

创建 pre-merge-commit 钩子 导航到 Git 仓库的钩子目录: cd /path/to/your/repo/.git/hooks创建或编辑 pre-merge-commit 钩子: 也可以通过指令创建 nano pre-merge-commit在钩子文件中添加以下代码: #!/bin/sh# 获取当前分支名称 curr…...

第二节:如何使用thymeleaf渲染html(自学Spring boot 3.x的第一天)

大家好&#xff0c;我是网创有方&#xff0c;今天来学习如何使用thymeleaf渲染html。该模板运用不广泛&#xff0c;所以本节内容了解既可。 第一步&#xff1a;创建html文件。 在模板templates目录下创建一个html文件。 编写代码如下&#xff1a; <!DOCTYPE html> <…...

计算机相关术语科普之什么叫网关(Gateway)

网关&#xff08;Gateway&#xff09;是一个在计算机网络中起到关键作用的设备或系统&#xff0c;它扮演着网络间连接器或协议转换器的角色。 一、定义与功能 1&#xff09;定义&#xff1a; 网关是在不同网络之间实现互连的复杂设备&#xff0c;仅用于两个高层协议不同的网…...

B站网页部分API

https://www.bilibili.com/ 数据结构 mid: 用户id name: 用户名 face: 用户头像url noface.jpg为默认头像 sign&#xff1a; 签名level: b站等级 coins: b站硬币粉丝 https://api.bilibili.com/x/relation/fans?vmid{mid}&pn{pn}&ps{limit}&orderdesc&…...

使用Spring Boot和Spring Security保护你的应用

使用Spring Boot和Spring Security保护你的应用 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将深入探讨如何利用Spring Boot和Spring Security来保护…...

CVE-2019-12272 Openwrt可视页面LuCi命令注入漏洞复现(完结)

声明 本文所使用的一些源代码等内容已经上传至github&#xff0c;具体地址如下 Vulnerability_POC-EXP/OpenWrt/CVE-2019-12272 at main a2148001284/Vulnerability_POC-EXP GitHub 漏洞简介 参考内容&#xff1a; CVE-2019-12272 OpenWrt图形化管理界面LuCI命令注入分析 |…...

【多线程开发 4】从源码学习LockSupport

从源码学习LockSupport 2024年6月30日 大家好啊&#xff0c;好久没写博客了&#xff0c;今天打算写一下&#xff0c;讲一下JUC里面LockSupport这个类。 这个是一个工具类&#xff0c;实际上也是为了线程通信开发的。它的源码比较短&#xff0c;也只引用了Unsafe一个类。所以…...

gameui C++的代码

gameui C的代码 #include <graphics.h> #include "gameboard.h" const int WIDTH 560; const int HEIGHT 780; const int GRID_SIZE 120; class GameUi { private: public:GameUi(GameBoard& gb) {// 初始化图形窗口initgraph(WIDTH, HEIGHT);// 设置…...

1.什么是js?特点是什么?组成部分?

Js是一种直译式脚本语言&#xff0c;一种动态类型&#xff0c;弱类型&#xff0c;基于原型的高级语言。 直译式&#xff1a;js程序运行过程中直接编译成机器语言。 脚本语言&#xff1a;在程序运行过程中逐行进行解释说明&#xff0c;不需要预编译。 动态类型&#xff1a;js…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...

倒装芯片凸点成型工艺

UBM&#xff08;Under Bump Metallization&#xff09;与Bump&#xff08;焊球&#xff09;形成工艺流程。我们可以将整张流程图分为三大阶段来理解&#xff1a; &#x1f527; 一、UBM&#xff08;Under Bump Metallization&#xff09;工艺流程&#xff08;黄色区域&#xff…...