从 Monolith 到 Modular(一个基础简单的示例)

发布: (2025年12月10日 GMT+8 05:29)
4 min read
原文: Dev.to

Source: Dev.to

我通过拆解自己的代码来学习系统设计。

第 1 阶段:简单单服务器(2‑层)

代码仓库: arsalanbardsiri/simple-single-server-app

每个伟大的系统都始于单体。我的第一次迭代是经典的 “2‑层” 应用。在这种布局下,架构看起来异常简单:

  • 客户端层: 用户界面(浏览器)。
  • 服务器层: 一台机器同时处理业务逻辑(Web 服务器)和数据持久化(数据库)。

架构图

Architecture diagram

为什么从这里开始?

这是最快的交付方式。应用与数据库之间没有网络延迟,因为它们共享同一硬件。部署只需一条命令。对于学生项目或概念验证,这非常合适。

陷阱

然而,这种简化是一种陷阱。

  • 垂直扩展限制: 想要容纳更多用户时必须升级 整台 服务器(更多内存、更强 CPU),无法单独升级数据库。
  • 单点故障 (SPOF): 如果 Web 服务器因脚本错误崩溃,数据库也会随之宕机。
  • 安全风险: 在 2‑层架构中,数据库通常与面向公众的 Web 服务器共享同一环境,攻击面增大。

第 2 阶段:向 3‑层架构演进

代码仓库: arsalanbardsiri/3tier-simple-app

为了解决单服务器的脆弱性,我将应用重构为 3‑层架构。这之所以成为业界标准并非没有理由。它在物理和逻辑上将系统划分为三个独立层次。

架构图

3‑Tier diagram

  • 表示层: 用户看到的前端(客户端)。
  • 应用层: 处理请求的后端 API(业务逻辑)。
  • 数据层: 用于存储信息的专用数据库服务器。

“啊哈!”时刻

迁移到此架构会带来复杂性——我必须管理连接字符串、网络延迟以及多次部署。那么,为什么要这么做?

  1. 独立可扩展性
    如果应用需要进行大量计算(CPU 密集),我可以在不动数据库的情况下增加 应用服务器。如果需要存储海量日志(存储密集),可以单独升级 数据库服务器

  2. 提升安全性
    在单服务器应用中,数据库位于面向公众的服务器上。而在 3‑层应用中,数据库层被隐藏在应用层之后,位于仅能被应用服务器访问的私有网络中。

  3. 容错性
    通过解耦各组件,系统能够容忍重启。为部署补丁而重启 Web 服务器不会影响数据库。

接下来怎么办?

我已经成功实现了关注点分离,但仍然只有一个应用服务器和一个数据库服务器,仍是单点故障。ByteByteGo 路线图的下一步是实现 负载均衡器(可能使用 NGINX),将流量分配到多个应用服务器上,从而在任意一台宕机时用户仍然感受不到影响。

关注代码演进

Back to Blog

相关文章

阅读更多 »