01 我想开始了解后端

5 阅读13分钟

AI编程的发展让我很惶恐。我不知道做什么,不知道未来在哪里。但是我知道,我现在不能停下来。因为我不想被淘汰...

给前端工程师的后端入门地图:Rust + Flutter 即时聊天工具

你是谁:已经会前端,理解组件、状态、请求接口、构建工具,现在要用 Flutter + Rust 做一个即时聊天工具。

本文目标:用前端熟悉的方式理解后端要学什么、Java / Rust 和前端的差异,以及数据库、Redis、Apollo、消息队列等组件分别是什么意思。

1. 先建立一张全局图

一个 IM(即时聊天)系统不是只有「发一条消息」这么简单。它通常至少包含这些部分:


flowchart LR

Client[Flutter 客户端] -->|HTTP 登录/拉历史| API[后端 HTTP API]

Client -->|WebSocket 长连接| Gateway[实时连接网关]


API --> Auth[鉴权与用户服务]

Gateway --> Msg[消息服务]

Msg --> DB[(数据库)]

Msg --> Redis[(Redis)]

Msg --> MQ[消息队列]

API --> Config[Apollo/配置中心]

Gateway --> Config

MQ --> Worker[异步任务 Worker]

Worker --> Push[离线推送/审核/通知]

用前端语言理解:

组件前端类比后端里真正负责的事
Flutter 客户端React/Vue 页面 + App 状态展示聊天列表、输入消息、维护本地 UI 状态。
Flutter 客户端React/Vue 页面 + App 状态展示聊天列表、输入消息、维护本地 UI 状态。
HTTP API你平时调用的 REST 接口登录、注册、查用户、拉历史消息、上传资料。
WebSocket 网关一个长期不断开的 fetch实时收发消息、在线状态、输入中、已读回执。
数据库持久化版的全局 store长期保存用户、好友关系、群、消息记录。
Redis超高速临时 store / 内存缓存在线状态、验证码、限流计数、热点数据、短期会话。
消息队列异步事件总线把“发消息后还要做的事”异步化,例如离线推送。
Apollo 配置中心远程 .env + Feature Flag动态改配置,不必每次重新发版。
Worker后台任务脚本消费队列,做推送、审核、统计、补偿任务。

2. 前端、后端、数据库到底怎么分工

2.1 前端负责「体验」

前端更接近:

  • 页面布局、交互、动画;
  • 本地状态管理;
  • 调用接口;
  • 展示 loading / error / empty;
  • 缓存少量本地数据;
  • 处理弱网、重试、断线提示。

前端状态通常是「用户当前正在看的状态」。它可以丢,可以重新拉。

2.2 后端负责「规则和事实」

后端更接近:

  • 判断用户是谁;
  • 判断用户有没有权限;
  • 校验请求是否合法;
  • 写入数据库;
  • 保证消息 ID、顺序、去重;
  • 给在线用户实时投递;
  • 给离线用户后续补发或推送;
  • 记录日志,方便排查问题。

后端保存的是「系统承认的事实」。例如一条消息是否发送成功,最终以后端落库为准,不以后端返回前的 UI 乐观状态为准。

2.3 数据库负责「长期事实」

数据库不是后端本身,而是后端依赖的一个存储系统。

前端可以把数据放在 statelocalStorageIndexedDB 里;但这些都是用户设备上的数据。后端数据库是服务端统一保存的数据来源。

比如 IM 里:

数据应该放哪里原因
用户账号数据库需要长期保存。
密码哈希数据库需要安全保存,不能明文。
好友关系数据库是业务事实。
群成员数据库是权限判断依据。
历史消息数据库用户换设备也要能查。
用户是否在线Redis高频变化,不适合作为长期事实。
验证码Redis几分钟过期。
当前 WebSocket 连接在哪台机器Redis / 内存临时路由信息。

3. Java、Rust、前端的学习差异

3.1 三者写代码时的关注点

维度前端 JS/TSJava 后端Rust 后端
主要运行位置浏览器 / AppJVM 进程原生服务进程
典型框架React、Vue、FlutterSpring BootAxum、Actix Web
包管理npm、pnpmMaven、GradleCargo
配置文件package.jsonpom.xml / build.gradleCargo.toml
类型系统TS 是编译期辅助,运行时仍是 JS强类型,运行在 JVM强类型,编译成机器码
内存管理JS 引擎 GCJVM GC无 GC,所有权模型
错误处理try/catch、Promise reject异常、错误码ResultOption?
并发模型事件循环、Promise线程池、虚拟线程、异步框架Tokio async、任务、通道
常见优势开发 UI 快企业生态成熟性能、内存、安全边界强
常见门槛浏览器兼容、状态复杂框架厚、概念多所有权、生命周期、异步边界

3.2 用前端经验理解 Java

Java 后端常见组合是:


Spring Boot + MySQL/PostgreSQL + Redis + MQ + 配置中心

你可以粗略类比为:

Java 后端前端类比
Spring BootNext.js / Nuxt 这种全家桶框架
ControllerAPI Route / 路由处理函数
Service业务逻辑层,类似抽出来的业务 hooks/service
Repository / Mapper数据访问层,专门查数据库
DTO前后端传输的数据结构
Entity数据库表对应的对象
Bean / IoC框架帮你创建并注入模块实例

Java 的好处是资料多、企业案例多、组件成熟;缺点是框架概念比较厚,初学时容易被注解、分层、配置淹没。

3.3 用前端经验理解 Rust

Rust 后端常见组合是:


Axum + Tokio + SQLx/SeaORM + PostgreSQL + Redis

你可以粗略类比为:

Rust 后端前端类比
Cargopnpm/npm + 构建工具
Axum 路由Express / API Route
Handler接口处理函数
Extractor从请求里取 path、query、body、header
serdeJSON 序列化/反序列化工具
Result<T, E>明确的成功/失败返回
Option<T>明确的 T | null
Tokio后端异步运行时,类似更底层的事件循环

Rust 的好处是性能好、类型严、适合长连接和高并发;缺点是入门期会被所有权、借用、生命周期卡住。

4. 后端必须学习的核心技能

4.1 HTTP API

这是后端入门第一层。

你需要理解:

  • GET / POST / PUT / DELETE
  • URL、Query、Header、Body;
  • JSON;
  • 状态码:200400401403404500
  • REST API;
  • CORS;
  • 接口版本;
  • 请求幂等性。 前端类比:你以前只是调用 API,现在你要设计 API。

4.2 WebSocket

IM 必须重点学 WebSocket。

HTTP 更像「问一次,答一次」;WebSocket 更像「建立一条一直开着的电话线」。

IM 里 WebSocket 常处理:

  • 用户上线;
  • 服务端主动推新消息;
  • 客户端发送消息;
  • 心跳;
  • 断线重连;
  • 消息 ACK;
  • 已读回执;
  • 输入中状态。

需要特别注意:WebSocket 连接是有状态的。你的后端要知道「这个用户当前连接在哪台服务器上」。

4.3 鉴权与权限

后端要回答两个问题:

  1. 你是谁?
  2. 你能不能做这件事?

常见概念:

名词含义
登录用户证明自己身份。
Token登录成功后发给客户端的凭证。
JWT一种常见 token 格式,里面可带用户信息和过期时间。
Session服务端保存登录状态,客户端只拿 session id。
RBAC基于角色的权限控制。
密码哈希密码不能明文入库,要用 Argon2、bcrypt 等算法处理。

前端可以隐藏按钮,但真正的权限必须由后端判断。

4.4 数据库与 SQL

先学关系型数据库,例如 PostgreSQL 或 MySQL。

你需要理解:

  • 表、行、列;
  • 主键;
  • 外键;
  • 索引;
  • 事务;
  • SQL;
  • 数据迁移;
  • 连接池;
  • 慢查询。

IM 里可能有这些表:

存什么
users用户账号、昵称、头像。
conversations单聊/群聊会话。
conversation_members会话成员。
messages消息正文、发送人、时间、序号。
message_receipts已读、送达状态。

4.5 Redis

Redis 是内存型数据存储,速度很快,通常用于缓存和临时状态。

它不等于数据库,虽然它也能存数据。区别是:

维度数据库Redis
主要用途长期保存业务事实缓存、临时状态、高频读写
数据位置主要面向磁盘持久化主要在内存
典型数据用户、订单、消息历史验证码、在线状态、限流计数
查询能力SQL、复杂查询、事务能力强Key-Value 操作快
丢失影响通常不能丢设计上应尽量可恢复

IM 里的 Redis 用法

  • 保存用户在线状态;
  • 保存用户连接在哪台网关;
  • 限制接口频率;
  • 存验证码;
  • 缓存用户资料;
  • 做分布式锁;
  • 用 Pub/Sub 或 Stream 做简单消息流。

4.6 消息队列

消息队列不是聊天消息本身,而是一种后端内部的异步通信工具。 比如用户发了一条消息,核心路径只做:


校验权限 -> 消息落库 -> 投递在线用户 -> 返回 ACK

其他事情可以丢到队列:


离线推送
内容审核
敏感词扫描
搜索索引
统计报表
AI 摘要

常见队列:

名称粗略理解
Kafka高吞吐日志型消息系统,大规模常见。
RabbitMQ传统消息队列,路由能力强。
NATS轻量、高性能消息系统。
Redis StreamRedis 里的流式队列能力。

4.7 Apollo 是什么

这里要区分两个常见的 Apollo。

名称场景含义
Apollo 配置中心国内后端常说的 Apollo携程开源的配置中心,用来动态管理服务配置。
Apollo GraphQL前端/GraphQL 生态GraphQL 客户端和服务端工具链。

如果后端同事说「接 Apollo 配置」,大概率指 配置中心

配置中心解决的问题是:不要把所有配置都写死在代码或 .env 里。

比如:

配置为什么适合放配置中心
Redis 地址不同环境不一样。
数据库连接开发、测试、生产不同。
是否开启注册可以动态开关。
消息最大长度可以不用发版就调整。
AI 审核开关模型异常时可以快速关闭。

前端类比:它像远程 .env + feature flag 管理后台。

5. IM 后端要额外关注什么

普通 CRUD 后端主要是「请求进来,查库,返回」。IM 后端多了实时性和连接状态。

5.1 消息 ID

每条消息都应该有唯一 ID。它用于:

  • 去重;
  • 排序;
  • 客户端本地消息和服务端消息对齐;
  • 断线重连后补拉。

5.2 消息顺序

用户关心聊天里的顺序。你需要考虑:

  • 同一个会话里的消息如何排序;
  • 服务端时间和客户端时间冲突怎么办;
  • 多设备同时发送怎么办;
  • 断线重连后如何补齐缺失消息。

5.3 ACK 和重试

客户端发送消息后,不能只靠 UI 判断成功。

常见状态:


本地创建 -> 发送中 -> 服务端已收到 -> 已投递 -> 已读

前端的“发送成功”最好对应后端 ACK。

5.4 在线和离线

在线用户可以通过 WebSocket 立即推送。离线用户要:

  • 保存消息;

  • 等用户上线后补拉;

  • 可选发送系统推送;

  • 避免重复推送。

5.5 多端同步

一个用户可能同时登录手机、平板、电脑。后端要考虑:

  • 发给当前用户的其他设备;

  • 已读状态同步;

  • 撤回消息同步;

  • 登录挤下线策略。


6. 推荐学习路线

第 1 阶段:后端基础

目标:能写最简单的 HTTP API。

  • Rust 基础语法;

  • Cargo;

  • Axum 路由;

  • JSON;

  • HTTP 状态码;

  • 错误处理;

  • 日志。

练习:

GET /v
POST /users/register
POST /users/login
GET /me

第 2 阶段:数据库

目标:数据能长期保存。

  • PostgreSQL 或 MySQL;
  • SQL;
  • 表设计;
  • 索引;
  • 事务;
  • 连接池;
  • migration;
  • Rust 里的 SQLx 或 SeaORM。

练习:

注册用户写入 users 表
登录时查询 users 表
创建 conversations 表
创建 messages 表

第 3 阶段:鉴权

目标:后端知道用户是谁。

  • 密码哈希;

  • JWT 或 Session;

  • Middleware;

  • 权限校验;

  • Token 过期和刷新。

练习:

只有登录用户才能创建会话
只有会话成员才能发送消息

第 4 阶段:WebSocket

目标:能实时收发消息。

  • WebSocket 连接建立;

  • 心跳;

  • 断线重连;

  • 消息 ACK;

  • 用户连接管理;

  • Tokio 任务和 channel。

练习:

客户端 A 发消息
服务端通过 WebSocket 推给客户端 B
客户端 B 返回 ACK

第 5 阶段:Redis

目标:管理临时状态和高频数据。

  • Key-Value;

  • 过期时间;

  • Hash;

  • Set;

  • 限流;

  • 在线状态;

  • 分布式锁基础。

练习:

用户上线时写入 online:user_id
断线或心跳超时后删除在线状态
验证码 5 分钟过期

第 6 阶段:队列和异步任务

目标:把非核心流程从发消息主链路拆出去。

  • MQ 基础;
  • 生产者/消费者;
  • 重试;
  • 死信队列;
  • 幂等处理。

练习:


消息落库后发出 MessageCreated 事件
Worker 消费事件并做离线推送

第 7 阶段:配置、部署和观测

目标:服务能在真实环境运行和排查。

  • 环境变量;
  • 配置中心 Apollo;
  • Docker;
  • Linux;
  • 日志;
  • metrics;
  • tracing;
  • 健康检查;
  • 灰度发布。

7. Rust 后端技术栈建议

如果这个项目主要想用 Rust 做后端,可以从下面这套开始:

能力推荐
Web 框架Axum
异步运行时Tokio
JSON 序列化serde / serde_json
数据库PostgreSQL
数据库访问SQLx 或 SeaORM
缓存Redis
日志tracing
配置config / envy,后续接 Apollo
API 文档OpenAPI / utoipa
部署Docker

学习时不要一开始就把所有组件都接上。更稳的顺序是:


Axum HTTP -> PostgreSQL -> 登录鉴权 -> WebSocket -> Redis -> MQ -> Apollo/部署/监控


8. 最小 IM 后端 MVP 范围

第一版不要做太大。建议 MVP 只包含:

  • 用户注册;
  • 用户登录;
  • 创建单聊会话;
  • 发送文本消息;
  • 查询历史消息;
  • WebSocket 实时投递;
  • 简单 ACK;
  • 断线后重新拉历史消息。

暂时不要急着做:

  • 大群;
  • 端到端加密;
  • 消息漫游复杂策略;
  • 多机房;
  • 复杂审核;
  • AI 助手;
  • 高级搜索;
  • 精细已读回执。

这些都可以后续迭代。


9. 最重要的心智转换

前端入门后端,最容易卡在「我能不能写出接口」;但真正的后端思维是:

问题后端要考虑
这个请求是谁发的?鉴权。
他有没有权限?权限模型。
数据是否可信?参数校验。
写库失败怎么办?错误处理和事务。
重复请求怎么办?幂等。
并发同时修改怎么办?锁、事务、版本号。
服务重启会不会丢数据?持久化。
用户断线怎么办?重连和补偿。
出问题怎么查?日志、trace、metrics。

一句话总结:

前端更关注「用户此刻看到什么」;后端更关注「系统最终承认什么事实,以及这个事实是否可靠」。


10. 建议你接下来怎么学

  1. 用 Axum 写 3 个 HTTP 接口:/v、注册、登录。

  2. 接 PostgreSQL,把用户写进数据库。

  3. 加密码哈希和 JWT。

  4. 写一个 WebSocket echo 服务。

  5. 把 echo 改成单聊消息投递。

  6. 加 Redis 保存在线状态。

  7. 再考虑消息队列、Apollo、部署和监控。

学后端不要一开始追求架构完整。先让一条消息从 Flutter 发到 Rust,再从 Rust 推到另一个 Flutter 客户端;这条链路跑通后,数据库、Redis、队列、配置中心的意义会自然变清楚。