SaaS全栈开发实战 · 从零到上线
技术选型是架构师最重要的决策之一。选对了,开发效率翻倍;选错了,技术债利滚利。本课将从SaaS产品的特殊需求出发,系统分析前端框架、后端语言、数据库、云服务的技术选型决策。
# 技术选型评估框架
from dataclasses import dataclass
from typing import List
@dataclass
class TechCandidate:
"""技术候选方案"""
name: str
category: str
learning_curve: int # 学习曲线(越低越好)
ecosystem: int # 生态系统
performance: int # 性能
scalability: int # 扩展性
community: int # 社区
hiring_pool: int # 招聘池
long_term: int # 长期存活
saas_fit: int # SaaS适配
STARTUP_WEIGHTS = {
'learning_curve': 0.15, 'ecosystem': 0.2, 'performance': 0.1,
'scalability': 0.15, 'community': 0.15, 'hiring_pool': 0.1,
'long_term': 0.05, 'saas_fit': 0.1,
}
def weighted_score(self, weights=None) -> float:
w = weights or self.STARTUP_WEIGHTS
scores = {
'learning_curve': 11 - self.learning_curve,
'ecosystem': self.ecosystem, 'performance': self.performance,
'scalability': self.scalability, 'community': self.community,
'hiring_pool': self.hiring_pool, 'long_term': self.long_term,
'saas_fit': self.saas_fit,
}
return sum(scores[k] * w[k] for k in w)
# ✅ 验证通过 - 后端技术选型
candidates = [
TechCandidate("FastAPI", "backend", 4,7,8,8,8,8,8,9),
TechCandidate("Express", "backend", 3,9,7,7,9,9,8,7),
TechCandidate("Spring Boot", "backend", 7,9,8,9,9,9,9,7),
TechCandidate("Go/Gin", "backend", 5,6,10,9,7,6,8,8),
]
for c in sorted(candidates, key=lambda x: x.weighted_score(), reverse=True):
print(f"{c.name}: {c.weighted_score():.2f}")
| 层级 | 技术 | 选择理由 |
|---|---|---|
| 前端 | React 18 + TypeScript | 生态最丰富,组件库最多 |
| 后端 | FastAPI (Python) | 异步高性能,自动API文档 |
| 数据库 | PostgreSQL 15 | JSONB+RLS,SaaS首选 |
| 缓存 | Redis 7 | 会话、限流、缓存一站式 |
| 容器化 | Docker + Compose | 环境一致,部署标准化 |
| CI/CD | GitHub Actions | 免费额度,深度集成 |
| 支付 | Stripe | 全球支付,SaaS计费API最完善 |
# FastAPI核心特性演示
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, EmailStr
from typing import Optional
from datetime import datetime
app = FastAPI(title="SaaS Platform API", version="1.0.0")
class UserCreate(BaseModel):
email: EmailStr
name: str
plan: str = "free"
class UserResponse(BaseModel):
id: int
email: str
name: str
plan: str
created_at: datetime
@app.post("/users", response_model=UserResponse, tags=["用户管理"])
async def create_user(user: UserCreate):
"""创建新用户 - 自动参数验证+API文档"""
return UserResponse(
id=1, email=user.email, name=user.name,
plan=user.plan, created_at=datetime.now()
)
@app.get("/users/{user_id}", response_model=UserResponse)
async def get_user(user_id: int):
"""获取用户 - 路径参数自动类型转换"""
if user_id <= 0:
raise HTTPException(status_code=404, detail="用户不存在")
return UserResponse(
id=user_id, email="user@example.com",
name="Demo", plan="pro", created_at=datetime.now()
)
# ✅ 验证通过 - FastAPI自动生成:
# - Swagger UI: http://localhost:8000/docs
# - ReDoc: http://localhost:8000/redoc
# - OpenAPI JSON: http://localhost:8000/openapi.json
print("FastAPI应用创建成功!")
| 维度 | PostgreSQL | MongoDB |
|---|---|---|
| 事务 | ✅ 完整ACID | ⚠️ 4.0后有限支持 |
| 数据一致性 | ✅ 强一致性 | ⚠️ 最终一致性 |
| JSON支持 | ✅ JSONB+索引 | ✅ 原生JSON |
| 复杂查询 | ✅ SQL全功能 | ❌ 聚合管道复杂 |
| 计费场景 | ✅ 精确计算 | ⚠️ 精度问题 |
| 多租户 | ✅ Schema/RLS隔离 | ⚠️ 应用层实现 |
-- PostgreSQL SaaS初始化
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
CREATE TYPE tenant_status AS ENUM ('trial', 'active', 'suspended', 'deleted');
CREATE TABLE tenants (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
name VARCHAR(255) NOT NULL,
slug VARCHAR(100) UNIQUE NOT NULL,
status tenant_status DEFAULT 'trial',
plan VARCHAR(50) DEFAULT 'free',
settings JSONB DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
deleted_at TIMESTAMPTZ
);
-- 自动更新时间戳
CREATE OR REPLACE FUNCTION update_timestamp()
RETURNS TRIGGER AS $$
BEGIN NEW.updated_at = NOW(); RETURN NEW; END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER tenants_updated_at
BEFORE UPDATE ON tenants
FOR EACH ROW EXECUTE FUNCTION update_timestamp();
-- ✅ 验证通过 - PostgreSQL DDL
mkdir -p saas-project/{backend,frontend,infra,docs}
mkdir -p saas-project/backend/{app/{api,core,models,schemas,services},tests,alembic}
mkdir -p saas-project/frontend/src/{components,features,hooks,stores,services,types}
mkdir -p saas-project/infra/{docker,scripts}
# 后端依赖
cat > saas-project/backend/requirements.txt << 'EOF'
fastapi==0.108.0
uvicorn[standard]==0.25.0
sqlalchemy==2.0.25
alembic==1.13.0
psycopg2-binary==2.9.9
redis==5.0.1
python-jose[cryptography]==3.3.0
passlib[bcrypt]==1.7.4
python-multipart==0.0.6
pydantic[email]==2.5.0
stripe==7.8.0
httpx==0.25.2
EOF
# docker-compose.yml
version: "3.9"
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: saas_db
POSTGRES_USER: saas_user
POSTGRES_PASSWORD: dev_password
ports: ["5432:5432"]
volumes: [pg_data:/var/lib/postgresql/data]
redis:
image: redis:7-alpine
ports: ["6379:6379"]
volumes:
pg_data:
每个重要技术决策都应该记录下来,包括背景、选项、决策和后果。这种文档叫做ADR(Architecture Decision Record):
# ADR模板
ADR_TEMPLATE = """
# ADR-001: 选择FastAPI作为后端框架
## 状态
已接受
## 背景
需要为SaaS产品选择后端框架,考虑因素:
- 开发效率(小团队2-3人)
- 异步支持(实时功能需求)
- API文档自动生成
- Python生态(数据分析/ML需求)
## 决策
选择FastAPI,而非Django/Flask/Express
## 选项分析
| 框架 | 优势 | 劣势 | 评分 |
|------|------|------|------|
| FastAPI | 异步、自动文档、高性能 | 生态较新 | 9/10 |
| Django | 成熟、Admin后台 | 同步、重 | 7/10 |
| Flask | 轻量、灵活 | 功能少 | 6/10 |
| Express | 生态大、同语言 | 回调地狱 | 7/10 |
## 后果
- 正面:开发速度快、API文档零维护
- 负面:社区资源比Django少,需自己实现Admin
- 风险:框架较新,长期存活性待验证(缓解:核心稳定,大厂使用)
"""
# ✅ 验证通过 - ADR决策记录
# 技术债追踪
class TechDebtTracker:
"""技术债追踪器"""
DEBT_LEVELS = {
'critical': '必须立即解决,影响生产',
'high': '近期必须解决,1-2个Sprint内',
'medium': '计划解决,3-6个月内',
'low': '有时间再解决',
}
def __init__(self):
self.debts = []
def add_debt(self, description: str, level: str,
estimated_effort: str, reason: str):
self.debts.append({
'description': description,
'level': level,
'effort': estimated_effort,
'reason': reason, # 为什么产生了技术债
'created_at': 'now',
})
def get_critical(self):
return [d for d in self.debts if d['level'] == 'critical']
# ✅ 验证通过 - 技术债管理
\n
每个技术决策都应记录理由,ADR是团队沟通和未来回溯的重要工具:
# ADR-001: 选择FastAPI
ADR = {
"编号": "ADR-001",
"标题": "选择FastAPI作为后端框架",
"状态": "已接受",
"背景": "SaaS产品需要高性能API、自动文档、Python生态",
"决策": "选择FastAPI,而非Django/Flask/Express",
"选项分析": {
"FastAPI": {"优势": "异步+自动文档+高性能", "劣势": "生态较新", "评分": 9},
"Django": {"优势": "成熟+Admin后台", "劣势": "同步+重量级", "评分": 7},
"Express": {"优势": "生态大+前后端同语言", "劣势": "回调问题", "评分": 7},
},
"后果": {
"正面": "开发速度快、API文档零维护",
"负面": "社区资源比Django少",
"缓解": "核心稳定,大厂(Netflix/Microsoft)使用"
}
}
print(f"决策: {ADR['标题']} - {ADR['状态']}")
# 技术债追踪系统
class TechDebtTracker:
LEVELS = {'critical': '必须立即解决', 'high': '1-2Sprint内',
'medium': '3-6月内', 'low': '有时间再说'}
def __init__(self):
self.debts = []
def add(self, desc: str, level: str, effort: str, reason: str):
self.debts.append({'desc': desc, 'level': level,
'effort': effort, 'reason': reason})
def report(self):
for level in ['critical', 'high', 'medium', 'low']:
items = [d for d in self.debts if d['level'] == level]
if items:
print(f"\n{level.upper()}: {self.LEVELS[level]}")
for d in items:
print(f" - {d['desc']} (工作量: {d['effort']})")
tracker = TechDebtTracker()
tracker.add("硬编码配置", "high", "1天", "快速原型")
tracker.add("缺少单元测试", "medium", "3天", "时间紧")
tracker.report()
SaaS后端开发不仅要写代码,更要建立可持续的工程实践。以下是关键的非功能性工作:
# 代码质量配置
# pyproject.toml
QUALITY_CONFIG = {
"linting": "ruff check . --fix",
"formatting": "black . --line-length 100",
"type_checking": "mypy app/ --strict",
"complexity": "radon cc app/ -a -nc", # 复杂度检查
"security": "bandit -r app/", # 安全扫描
}
# pre-commit钩子 (.pre-commit-config.yaml)
PRE_COMMIT_HOOKS = """
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
hooks: [ruff]
- repo: https://github.com/psf/black
hooks: [black]
- repo: https://github.com/pre-commit/mirrors-mypy
hooks: [mypy]
"""
print("代码质量工具配置完成")
# app/core/sentry.py - 错误追踪
import sentry_sdk
from sentry_sdk.integrations.fastapi import FastApiIntegration
def init_sentry(dsn: str, environment: str):
sentry_sdk.init(
dsn=dsn,
environment=environment,
integrations=[FastApiIntegration()],
traces_sample_rate=0.1, # 10%请求追踪
profiles_sample_rate=0.1,
)
# ✅ 验证通过 - Sentry错误追踪
本课内容是SaaS全栈开发的重要一环。以下是推荐的深入学习资源:
学完本课后,建议你:
💡 学习建议:每课花2-3小时(1小时阅读+1-2小时动手实践),40课约80-120小时,约4-6周可完成全课程。坚持每天1课,6周后你就是SaaS全栈开发者!
完成本课后,你已解锁:
技术选型框架 FastAPI入门 React+TS初始化 PostgreSQL设计 Docker环境✅ 你现在能为SaaS项目做出合理的技术选型了!