后端项目架构设计指南:从脚本到微服务的分层演进实战(Easy-Vibe 项目学习版)

  • 教程
  • 文档

【免费下载链接】easy-vibe

从 0 到 1 学会 vibe coding,项目制学习

项目地址: https://gitcode.com/datawhalechina/easy-vibe
点击查看 免费下载

后端项目从几行脚本成长到支撑百万用户的分布式系统,代码的组织方式决定了它的生死。这篇指南以 Easy-Vibe 开源教程仓库中《后端项目架构设计》为核心,系统讲解如何根据用户规模与语言特性选择架构形态:入门级的简单脚本风格、中等级的四层架构(Controller-Service-Repository-Model)、企业级的微服务与数据层设计,并给出 Node.js、Python、Go、Java 四种语言从零到企业级的完整目录与代码示例。读完本文,你将掌握一套"按业务规模渐进式演进"的架构决策方法论,并能在实际项目中直接套用文中给出的工程结构。


1. 架构演进:从脚本到系统

1.1 按用户规模划分架构等级

后端项目架构必须与业务规模和用户量匹配。过度的架构设计是浪费,不足的架构设计则会在业务增长后成为重构的沉重负担。下表给出了按用户数与并发请求量划分的三个典型架构等级:

等级用户数并发请求数典型场景核心关注点
入门级< 1k< 100个人项目、MVP、内部工具快速开发、简单部署
中等级1k-100k100-10k企业系统、SaaS、中型平台分层架构、编码规范
企业级> 100k> 10k大型平台、互联网应用微服务、高可用、性能优化

1.2 按语言特性选择架构风格

每种编程语言都有自己的设计哲学和生态,架构设计应当顺应语言特性,而不是生搬硬套其他语言的模式:

语言设计哲学推荐架构代表框架
Node.js事件驱动、非阻塞 I/O分层架构 + 异步流程Express、NestJS、Fastify
Python简洁优雅、快速开发MTV/MVC、分层架构Django、Flask、FastAPI
Go简洁高效、原生并发简洁分层、微服务Gin、Echo、Fiber
Java企业级、强类型严格分层、领域驱动Spring Boot、Spring Cloud

1.3 架构选型四原则

::: tip 💡 架构选择原则

  1. 不要过度设计:小项目用简单架构,大项目才需要复杂架构
  2. 顺应语言特性:不要试图在 Python 里写 Java 风格的代码
  3. 渐进式演进:先简单起步,随业务增长逐步优化
  4. 团队熟悉度:选择团队熟悉的架构风格,降低学习成本 :::

2. 入门级架构(用户 < 1k)

2.1 适用场景

  • 个人项目、学习练手
  • 创业团队 MVP(最小可行产品)
  • 内部工具、管理后台
  • 原型验证、概念演示

入门级架构的核心诉求是快速跑通:文件数量少、依赖简单、部署命令一行搞定。以下按四种语言分别给出最小可行结构。

2.2 Node.js —— 简单脚本风格

特点:单文件或简单拆分,启动快。

my-node-api/
├── src/
│   ├── app.js              # 应用入口
│   ├── routes.js           # 路由定义
│   ├── db.js               # 数据库连接
│   └── utils.js            # 工具函数
├── .env                    # 环境变量
├── package.json
└── README.md

代码示例:

// src/app.js
const express = require('express');
const app = express();

app.use(express.json());

// 直接在入口编写路由(适用于端点极少的场景)
app.get('/users', async (req, res) => {
  const users = await db.query('SELECT * FROM users');
  res.json(users);
});

app.post('/users', async (req, res) => {
  const { name, email } = req.body;
  const result = await db.query(
    'INSERT INTO users (name, email) VALUES (?, ?)',
    [name, email]
  );
  res.status(201).json({ id: result.insertId });
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

这一风格在 Easy-Vibe 仓库中有真实的落地示例:examples/trae-3d-block-game 是一个基于 Three.js + Electron 的 3D 方块游戏项目,其 package.json 中把 dev:web、build:web、dev:electron、build 等脚本集中声明,配合 vite.config.js 完成构建配置;入口文件 electron/main.js 只负责创建窗口与加载页面,游戏逻辑则收敛在 src/main.js 的 CONFIG 与 gameState 等模块中。这正是"脚本风格"的升级形态:入口薄、逻辑独立、脚本化构建。

2.3 Python —— 快速原型风格

特点:利用 Python 的简洁性快速实现功能。

my-python-api/
├── app.py                  # 主应用
├── models.py               # 数据模型
├── config.py               # 配置
├── requirements.txt
└── README.md

代码示例(Flask):

# app.py
from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
db = SQLAlchemy(app)

# 模型定义
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80), nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)

# 路由
@app.route('/users', methods=['GET'])
def get_users():
    users = User.query.all()
    return jsonify([{'id': u.id, 'name': u.name, 'email': u.email} for u in users])

@app.route('/users', methods=['POST'])
def create_user():
    data = request.json
    user = User(name=data['name'], email=data['email'])
    db.session.add(user)
    db.session.commit()
    return jsonify({'id': user.id}), 201

if __name__ == '__main__':
    app.run(debug=True)

Flask 的 SQLAlchemy 模型把建表与查询封装在类定义中,debug=True 开启热重载,是原型验证阶段的高效组合。需要更现代的异步风格时,可参考 FastAPI 的声明式路由与依赖注入。

2.4 Go —— 标准库简洁风格

特点:仅依赖 Go 标准库,依赖最少。

my-go-api/
├── main.go                 # 入口
├── handlers.go             # 处理器
├── models.go               # 模型
├── db.go                   # 数据库
├── go.mod
└── README.md

代码示例:

// main.go
package main

import (
    "database/sql"
    "encoding/json"
    "log"
    "net/http"
    _ "github.com/mattn/go-sqlite3"
)

type User struct {
    ID    int    `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

var db *sql.DB

func main() {
    var err error
    db, err = sql.Open("sqlite3", "./app.db")
    if err != nil {
        log.Fatal(err)
    }

    http.HandleFunc("/users", usersHandler)
    log.Println("Server starting on :8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

func usersHandler(w http.ResponseWriter, r *http.Request) {
    switch r.Method {
    case http.MethodGet:
        getUsers(w, r)
    case http.MethodPost:
        createUser(w, r)
    }
}

func getUsers(w http.ResponseWriter, r *http.Request) {
    rows, _ := db.Query("SELECT id, name, email FROM users")
    defer rows.Close()

    var users []User
    for rows.Next() {
        var u User
        rows.Scan(&u.ID, &u.Name, &u.Email)
        users = append(users, u)
    }

    json.NewEncoder(w).Encode(users)
}

net/http 标准库 + 一个 SQLite 驱动即可构成完整服务,json 标签负责序列化映射,无需任何 Web 框架。当路由逐渐复杂时,再引入 chi 或 Gin 这类轻量路由也不迟。

2.5 Java —— Spring Boot 起步风格

特点:利用 Spring Boot 自动配置快速启动。

my-spring-app/
├── src/main/java/com/example/
│   ├── controller/
│   │   └── UserController.java
│   ├── model/
│   │   └── User.java
│   ├── repository/
│   │   └── UserRepository.java
│   └── Application.java
├── src/main/resources/
│   └── application.yml
├── pom.xml
└── README.md

代码示例:

// Application.java
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

// User.java
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;
    // getters and setters
}

// UserRepository.java
public interface UserRepository extends JpaRepository<User, Long> {
}

// UserController.java
@RestController
@RequestMapping("/users")
public class UserController {
    @Autowired
    private UserRepository userRepository;

    @GetMapping
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }

    @PostMapping
    public User createUser(@RequestBody User user) {
        return userRepository.save(user);
    }
}

Spring Boot 的 @SpringBootApplication 自动装配 + Spring Data JPA 的接口派生查询,让一个用户 CRUD 服务只需要 4 个类。这个入门结构已经隐含着 controller/repository/model 的分层雏形——当业务复杂后,它会自然演化为下一章的完整四层架构。


3. 中级架构(用户 1k-100k)

3.1 适用场景

  • 企业管理类系统(ERP、CRM、OA)
  • SaaS 应用
  • 电商平台
  • 需要多团队协作的项目

当业务从"几十个端点"膨胀到"几十个模块、多个团队并行开发",就必须引入分层架构来给代码画出清晰的边界。Easy-Vibe 仓库中专门有一篇姊妹文档《后端分层架构原理》详细论述了分层动机、依赖方向铁律与 DTO 设计,建议与本文配合阅读。

3.2 四层架构详解

中等级项目推荐采用 四层架构(Controller-Service-Repository-Model):

project/
├── src/
│   ├── controllers/          # 控制层:处理 HTTP 请求
│   ├── services/             # 服务层:业务逻辑
│   ├── repositories/         # 数据层:数据访问
│   ├── models/               # 模型层:数据结构
│   ├── middlewares/          # 中间件
│   ├── utils/                # 工具函数
│   ├── config/               # 配置
│   └── routes/               # 路由定义
├── tests/
├── docs/
└── scripts/

各层职责可以概括为一句口诀:

  • Controller 只负责"接单"——接收请求、校验参数、返回响应;
  • Service 只负责"掌勺"——编排业务逻辑、管理事务、协调多个 Repository;
  • Repository 只负责"取料"——数据库 CRUD、ORM 映射、查询封装;
  • Model/Domain 只负责"配方标准"——实体定义与业务规则。

依赖方向铁律:代码依赖必须指向更稳定、更抽象的方向——Controller 依赖 Service 接口、Service 依赖 Repository 接口、所有层依赖 Domain(业务核心、最稳定),严禁反向依赖(如 Repository 依赖 Service)。这一原则在分层架构文档中有完整的 DDD 与 DTO 案例说明。

3.3 Node.js —— 企业级分层

以 NestJS 为代表的模块化组织方式,按功能模块而非技术类型拆分:

node-enterprise/
├── src/
│   ├── modules/              # 按功能模块组织
│   │   ├── users/
│   │   │   ├── users.controller.ts
│   │   │   ├── users.service.ts
│   │   │   ├── users.repository.ts
│   │   │   ├── users.module.ts
│   │   │   └── dto/
│   │   ├── orders/
│   │   └── products/
│   ├── common/               # 公共模块
│   │   ├── filters/          # 异常过滤器
│   │   ├── guards/           # 守卫
│   │   ├── interceptors/     # 拦截器
│   │   └── pipes/            # 管道
│   ├── config/
│   └── main.ts

NestJS 代码示例:

// users/users.controller.ts
@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Get()
  findAll(@Query() query: QueryUserDto) {
    return this.usersService.findAll(query);
  }

  @Post()
  create(@Body() createUserDto: CreateUserDto) {
    return this.usersService.create(createUserDto);
  }
}

// users/users.service.ts
@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(User)
    private usersRepository: Repository<User>,
  ) {}

  async findAll(query: QueryUserDto) {
    const [data, total] = await this.usersRepository.findAndCount({
      skip: (query.page - 1) * query.limit,
      take: query.limit,
    });
    return { data, total };
  }

  async create(createUserDto: CreateUserDto) {
    const user = this.usersRepository.create(createUserDto);
    return this.usersRepository.save(user);
  }
}

3.4 Python —— Django/DRF 风格

Django 的"App 即模块"理念天然支持按业务领域组织代码:

django-enterprise/
├── apps/
│   ├── users/                # 用户应用
│   │   ├── models.py
│   │   ├── views.py          # API 视图
│   │   ├── serializers.py    # 序列化器
│   │   ├── permissions.py    # 权限
│   │   ├── urls.py
│   │   └── tests/
│   ├── orders/
│   └── products/
├── config/                   # 项目配置
│   ├── settings/
│   │   ├── base.py
│   │   ├── development.py
│   │   └── production.py
│   ├── urls.py
│   └── wsgi.py
├── utils/                    # 公共工具
├── templates/
├── static/
└── manage.py

Django REST Framework 代码示例:

# users/models.py
from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    phone = models.CharField(max_length=20, blank=True)
    avatar = models.URLField(blank=True)

# users/serializers.py
from rest_framework import serializers

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['id', 'username', 'email', 'phone', 'avatar']

# users/views.py
from rest_framework import viewsets, permissions
from rest_framework.decorators import action

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = [permissions.IsAuthenticated]

    @action(detail=False, methods=['get'])
    def me(self, request):
        serializer = self.get_serializer(request.user)
        return Response(serializer.data)

# users/urls.py
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register(r'users', UserViewSet)

urlpatterns = router.urls

注意 config/settings/ 下的 base.py / development.py / production.py 拆分:不同环境(开发/测试/生产)共享基础配置、各自覆盖差异项,这是 Django 项目进入中等级别后的标准做法。

3.5 Go —— 清洁架构风格

Go 中等级项目常采用"标准项目布局 + 清洁架构分层":

go-enterprise/
├── cmd/
│   └── api/                  # 应用入口
│       └── main.go
├── internal/                 # 私有代码
│   ├── domain/               # 领域层(实体、接口)
│   │   ├── user.go
│   │   └── repository.go
│   ├── usecase/              # 用例层(业务逻辑)
│   │   └── user_usecase.go
│   ├── delivery/             # 传输层(HTTP/gRPC)
│   │   └── http/
│   │       └── user_handler.go
│   ├── repository/           # 仓储层(数据访问)
│   │   └── user_repository.go
│   └── config/
├── pkg/                      # 公共库
├── migrations/
└── go.mod

清洁架构代码示例:

// domain/user.go
type User struct {
    ID        int64     `json:"id"`
    Username  string    `json:"username"`
    Email     string    `json:"email"`
    CreatedAt time.Time `json:"created_at"`
}

// domain/repository.go
type UserRepository interface {
    GetByID(ctx context.Context, id int64) (*User, error)
    GetByEmail(ctx context.Context, email string) (*User, error)
    Create(ctx context.Context, user *User) error
    Update(ctx context.Context, user *User) error
}

// usecase/user_usecase.go
type UserUsecase struct {
    userRepo UserRepository
}

func (u *UserUsecase) GetByID(ctx context.Context, id int64) (*User, error) {
    return u.userRepo.GetByID(ctx, id)
}

func (u *UserUsecase) Create(ctx context.Context, user *User) error {
    // 业务逻辑:校验邮箱是否已存在
    existing, _ := u.userRepo.GetByEmail(ctx, user.Email)
    if existing != nil {
        return errors.New("email already exists")
    }
    return u.userRepo.Create(ctx, user)
}

// delivery/http/user_handler.go
type UserHandler struct {
    UserUsecase *usecase.UserUsecase
}

func (h *UserHandler) GetUser(c *gin.Context) {
    id, _ := strconv.ParseInt(c.Param("id"), 10, 64)
    user, err := h.UserUsecase.GetByID(c.Request.Context(), id)
    if err != nil {
        c.JSON(404, gin.H{"error": "user not found"})
        return
    }
    c.JSON(200, user)
}

清洁架构的关键在于 domain 层不依赖任何外部框架,usecase 通过 UserRepository 接口编程,delivery 层的 Gin handler 只做协议转换。依赖方向由外向内、单向流动。

3.6 Java —— Spring Boot 企业级(DDD)

Java 中等级项目通常引入领域驱动设计(DDD)的包结构:

spring-enterprise/
├── src/main/java/com/example/
│   ├── application/          # 应用层
│   │   ├── controller/       # 控制器
│   │   ├── dto/              # 数据传输对象
│   │   └── assembler/        # 组装器
│   ├── domain/               # 领域层
│   │   ├── entity/           # 实体
│   │   ├── valueobject/      # 值对象
│   │   ├── repository/       # 仓储接口
│   │   └── service/          # 领域服务
│   ├── infrastructure/       # 基础设施层
│   │   ├── repository/       # 仓储实现
│   │   ├── config/           # 配置
│   │   └── common/           # 工具类
│   └── Application.java
├── src/main/resources/
│   ├── application.yml
│   └── mapper/
└── src/test/

DDD 代码示例:

// domain/entity/User.java
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String username;

    @Column(nullable = false, unique = true)
    private String email;

    @Embedded
    private UserStatus status;

    // 领域方法
    public void deactivate() {
        this.status = UserStatus.INACTIVE;
    }

    public boolean isActive() {
        return this.status == UserStatus.ACTIVE;
    }
}

// domain/repository/UserRepository.java
public interface UserRepository {
    Optional<User> findById(Long id);
    Optional<User> findByEmail(String email);
    User save(User user);
    void delete(User user);
}

// application/controller/UserController.java
@RestController
@RequestMapping("/api/v1/users")
@RequiredArgsConstructor
public class UserController {
    private final UserService userService;
    private final UserAssembler userAssembler;

    @GetMapping("/{id}")
    public ResponseEntity<UserDTO> getUser(@PathVariable Long id) {
        User user = userService.findById(id);
        return ResponseEntity.ok(userAssembler.toDTO(user));
    }

    @PostMapping
    public ResponseEntity<UserDTO> createUser(@RequestBody @Valid CreateUserRequest request) {
        User user = userService.createUser(request);
        return ResponseEntity.status(HttpStatus.CREATED)
                .body(userAssembler.toDTO(user));
    }
}

// infrastructure/repository/UserRepositoryImpl.java
@Repository
@RequiredArgsConstructor
public class UserRepositoryImpl implements UserRepository {
    private final UserJpaRepository jpaRepository;

    @Override
    public Optional<User> findById(Long id) {
        return jpaRepository.findById(id);
    }

    @Override
    public User save(User user) {
        return jpaRepository.save(user);
    }
}

DDD 结构把"业务规则"(deactivate、isActive)放进实体本身,把"接口定义"与"框架实现"分离(UserRepository 接口在 domain,UserRepositoryImpl 在 infrastructure),Controller 通过 DTO/Assembler 隔离前后端数据结构。

3.7 仓库佐证:Easy-Vibe 自身的工程组织

Easy-Vibe 仓库本身就是"中等级工程组织"的活教材:

  • 根目录 package.json 将 dev、build、test、lint、sitemap、book:pdf、book:epub 等脚本分层管理,测试脚本通过 node --test 自动发现 docs/scripts 下的用例;
  • 文档按 docs/zh-cn、docs/en、docs/ja-jp 等多语言目录组织,每个语言目录下再按 appendix(附录知识)、stage-1/2/3(实战阶段)分层,对应"按模块组织"的思路;
  • scripts 目录集中存放 build-locales.mjs、generate-sitemap.mjs、optimize-stage1-images.mjs 等构建工具,与四层架构中的 scripts/ 与 utils/ 职责对应;
  • 阶段二后端实战内容(docs/zh-cn/stage-2/backend)中的 cloud-server-deployment、database-supabase、zeabur-deployment、stripe-payment 等目录,正是"按业务/功能模块拆分目录"的实践。

4. 企业级架构(用户 > 100k)

4.1 适用场景

  • 大型互联网平台
  • 金融交易系统
  • 高并发电商系统
  • 需要多团队协作的大型项目

4.2 微服务架构

当单体应用无法再满足需求时,应转向微服务架构:

microservices-platform/
├── api-gateway/              # API 网关
│   ├── src/
│   └── Dockerfile
├── services/                 # 业务服务
│   ├── user-service/         # 用户服务
│   ├── order-service/        # 订单服务
│   ├── product-service/      # 商品服务
│   └── payment-service/      # 支付服务
├── shared/                   # 共享库
│   ├── proto/                # Protocol Buffers
│   ├── common-lib/
│   └── event-contracts/
├── infrastructure/           # 基础设施
│   ├── docker-compose.yml
│   ├── kubernetes/
│   └── terraform/
└── docs/

微服务的核心收益是独立部署、独立扩容、故障隔离,但代价是服务间通信与分布式数据一致性变得复杂。是否拆分取决于团队规模与运维能力,而非用户数的绝对值。

4.3 各语言微服务技术栈

语言微服务框架服务发现配置中心链路追踪
Node.jsNestJS + gRPCConsuletcdJaeger
PythonFastAPI + NamekoEurekaConsulZipkin
GoGo-kit + gRPCetcdetcdOpenTelemetry
JavaSpring CloudNacosNacosSkyWalking

4.4 代码仓库设计:Monorepo vs Polyrepo

Monorepo(单仓库):

monorepo/
├── services/
│   ├── user-service/         # 独立服务
│   │   ├── src/
│   │   ├── package.json
│   │   └── Dockerfile
│   ├── order-service/
│   └── product-service/
├── shared/
│   ├── types/                # 共享类型
│   ├── utils/                # 共享工具
│   └── proto/                # 共享协议
├── packages/
│   ├── eslint-config/        # 共享 ESLint 配置
│   └── ts-config/            # 共享 TS 配置
├── docker-compose.yml
└── package.json              # 根 package.json

优点:代码共享容易、构建发布统一、重构方便。 缺点:仓库体积大、权限管理复杂。

Polyrepo(多仓库):每个服务一个独立仓库。

优点:服务独立演进、团队自治、权限清晰。 缺点:代码共享困难、版本管理复杂。

Easy-Vibe 仓库本身采用的就是典型的 Monorepo 组织:多语言文档、示例项目(examples 下的 trae-3d-block-game、trae-block-game、trae-linear-dashboard 等)、脚本与配置集中在同一个仓库中,共享根 package.json 与 eslint.config.js。

4.5 数据层设计

数据库选型策略:不同类型的业务数据使用最合适的存储引擎。

数据类型推荐数据库适用场景
关系型数据PostgreSQL用户、订单、商品
缓存Redis会话、热点数据
搜索Elasticsearch商品搜索、日志
时序数据InfluxDB/TimescaleDB监控、指标
文档数据MongoDB日志、配置

数据访问层设计:

data-layer/
├── primary-db/               # 主数据库
│   ├── master/               # 写库
│   └── slaves/               # 读库
├── cache-layer/              # 缓存层
│   ├── redis-cluster/
│   └── local-cache/
├── search-engine/            # 搜索引擎
│   └── elasticsearch/
└── message-queue/            # 消息队列
    ├── kafka/
    └── rabbitmq/

数据层相关的深入主题,可继续阅读 Easy-Vibe 附录中的《缓存设计》《消息队列》《搜索引擎》等篇章;在阶段二实战中,database-supabase 展示了不自行运维数据库、直接使用托管数据库服务的实践路径。

4.6 仓库佐证:Easy-Vibe 的容器化部署

Easy-Vibe 仓库的 Dockerfile 展示了企业级部署的标准姿势——多阶段构建:第一阶段用 node:20-alpine 编译 VitePress 静态站点,第二阶段用 nginx:alpine 提供静态文件服务,并配合 nginx.conf 配置 gzip 压缩、静态资源一年强缓存(expires 1y)、SPA 路由回退(try_files ... /index.html)。这种"构建产物与运行环境解耦、镜像尽量精简"的做法,与微服务架构中"每个服务独立打包、独立部署"的理念一脉相承。


5. 开源项目架构参考

5.1 Node.js 生态

Express.js 官方项目结构:

express-project/
├── bin/                      # 启动脚本
├── public/                   # 静态资源
├── routes/                   # 路由
├── views/                    # 视图
├── app.js                    # 应用配置
└── package.json

NestJS 官方推荐:

nest-project/
├── src/
│   ├── modules/              # 功能模块
│   ├── common/               # 公共模块
│   ├── config/
│   └── main.ts
├── test/
└── nest-cli.json

5.2 Python 生态

Django 官方项目结构:

django-project/
├── project_name/             # 项目配置
├── apps/                     # 应用目录
├── templates/
├── static/
├── media/
└── manage.py

FastAPI 项目结构:

fastapi-project/
├── app/
│   ├── api/
│   │   ├── deps.py           # 依赖
│   │   └── v1/
│   │       └── endpoints/
│   ├── core/                 # 核心配置
│   ├── db/                   # 数据库
│   ├── models/               # 模型
│   ├── schemas/              # Pydantic 模型
│   └── main.py
├── tests/
└── alembic/                  # 迁移

FastAPI 结构中 schemas 目录(Pydantic 模型)与 models 目录(ORM 模型)分离,正是分层架构中"DTO 与实体隔离"的体现。

5.3 Go 生态

标准项目布局:

go-project/
├── cmd/                      # 应用入口
│   └── app/
│       └── main.go
├── internal/                 # 私有代码
├── pkg/                      # 公共库
├── api/                      # API 定义
├── web/                      # 静态资源
├── configs/                  # 配置
├── scripts/                  # 脚本
└── go.mod

internal/ 与 pkg/ 的区分是 Go 社区共识:internal 包只允许仓库内部导入,pkg 供外部复用,语言层面强制约束了架构边界。

5.4 Java 生态

Spring Boot 官方结构:

spring-boot-project/
├── src/main/java/com/example/
│   ├── controller/
│   ├── service/
│   ├── repository/
│   ├── entity/
│   ├── dto/
│   ├── config/
│   └── Application.java
├── src/main/resources/
│   ├── static/
│   ├── templates/
│   └── application.yml
└── src/test/

阿里巴巴 Java 开发手册要点:

  • 分层清晰:controller/service/manager/dao
  • 领域模型:区分 DO/DTO/BO/VO
  • 包结构:按功能模块划分

6. 架构演进路线图

6.1 演进示例

阶段 1:单体应用(入门级)
    ↓ 用户增长、团队扩张
阶段 2:分层架构(中等级)
    ↓ 业务复杂化、多团队协作
阶段 3:模块化/微服务(企业级)
    ↓ 高并发、高可用要求
阶段 4:云原生架构(平台级)

6.2 架构升级信号

信号当前等级建议升级方向
代码文件 > 50 个入门级中等级
构建时间 > 5 分钟中等级模块化
团队 > 10 人中等级微服务
日活用户(DAU)> 10 万中等级企业级
多语言技术栈单体微服务

这些信号不是绝对阈值,而是提醒你观察"痛感":当修改一个功能需要全局排查、构建一次等待过久、团队频繁冲突时,就是架构该升级的时刻。升级信号与"什么时候该拆、怎么拆"的完整讨论,可参考架构与系统设计附录(docs/en/appendix/6-architecture-and-system-design)中的单体到微服务专题。


7. 总结与最佳实践

::: tip 💡 核心思想 架构服务于业务,而不是为架构而架构。

按用户数选择:

  • < 1k:简单脚本,快速启动
  • 1k-100k:分层架构、编码规范
  • > 100k:微服务、高可用设计

按语言选择:

  • Node.js:善用异步特性,适合 I/O 密集型应用
  • Python:快速开发,适合数据处理与 AI 场景
  • Go:高性能,适合云原生与微服务
  • Java:企业级,适合大型复杂系统

通用原则:

  1. 渐进式演进:先简单起步,随业务成长
  2. 约定优于配置:统一规范,降低沟通成本
  3. 自动化测试:保障重构安全
  4. 文档先行:记录架构决策 :::

最终目标:无论规模大小,都让代码像工厂车间一样高效运转。

回顾全文,可以提炼出三条可落地的行动建议:

  1. 从最小可用结构开始:无论是个人项目还是内部工具,直接套用第 2 章对应语言的最小结构,两周内上线验证;
  2. 用分层四层架构承接增长:当模块与团队规模跨入中等级,按第 3 章的目录组织重构,用 DTO 隔离层间数据、用接口控制依赖方向;
  3. 用信号驱动升级而非提前设计:只有当第 6.2 节的信号真实出现时,才考虑模块化与微服务拆分,避免过度设计。

参考资源

  • 《Clean Architecture》—— Robert C. Martin:依赖规则与四层同心模型的经典著作
  • 《Building Microservices》—— Sam Newman:微服务架构的权威指南
  • 《Designing Data-Intensive Applications》—— Martin Kleppmann:数据密集型应用设计
  • 仓库配套阅读:《后端分层架构原理》《API 设计》《Web 框架》
  • 教程
  • 文档

【免费下载链接】easy-vibe

从 0 到 1 学会 vibe coding,项目制学习

项目地址: https://gitcode.com/datawhalechina/easy-vibe
点击查看 免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值