当前位置: 首页 > 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…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

基于SpringBoot在线拍卖系统的设计和实现

摘 要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统&#xff0c;主要的模块包括管理员&#xff1b;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发&#xff0c;旨在打造一个互动性强的购物平台&#xff0c;让用户在购物的同时&#xff0c;能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机&#xff0c;实现旋转、抽拉等动作&#xff0c;增…...

MySQL:分区的基本使用

目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区&#xff08;Partitioning&#xff09;是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分&#xff08;分区&#xff09;可以独立存储、管理和优化&#xff0c;…...

HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散

前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说&#xff0c;在叠衣服的过程中&#xff0c;我会带着团队对比各种模型、方法、策略&#xff0c;毕竟针对各个场景始终寻找更优的解决方案&#xff0c;是我个人和我司「七月在线」的职责之一 且个人认为&#xff0c…...

Sklearn 机器学习 缺失值处理 获取填充失值的统计值

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...

基于江科大stm32屏幕驱动,实现OLED多级菜单(动画效果),结构体链表实现(独创源码)

引言 在嵌入式系统中&#xff0c;用户界面的设计往往直接影响到用户体验。本文将以STM32微控制器和OLED显示屏为例&#xff0c;介绍如何实现一个多级菜单系统。该系统支持用户通过按键导航菜单&#xff0c;执行相应操作&#xff0c;并提供平滑的滚动动画效果。 本文设计了一个…...

用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法

用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法 大家好,我是Echo_Wish。最近刷短视频、看直播,有没有发现,越来越多的应用都开始“懂你”了——它们能感知你的情绪,推荐更合适的内容,甚至帮客服识别用户情绪,提升服务体验。这背后,神经网络在悄悄发力,撑起…...