返回首页
⚙️ 后端 / 架构

从单体到微服务:一家 5 人小团队的架构演进实录

我们 5 人团队 2 年内从 PHP 单体迁移到 Go 微服务的过程,包括踩过的 7 个坑和最终的技术栈选型。

微服务 · 架构演进 · 数据库 · Kubernetes
📰

今日技术简讯

📰 技术简讯 · 2026-07-03

今日聚合 7 条热门技术内容。

🤖 AI / LLM

1. Anthropic 推出 Skills 机制,Claude 可挂载工具集

  • 链接https://www.anthropic.com/news/skills
  • 来源:Anthropic 官方
  • 摘要:Skills 让 Claude 在对话中按需加载领域工具包(如 Office 工具、SQL 工具),上下文占用降低 80%。

2. Replit Agent 进入公测

  • 链接https://replit.com/agent
  • 来源:Replit 官方
  • 摘要:从一句话描述到完整可运行 App,平均耗时 12 分钟,已上线 10 万+ 项目。

🎨 前端 / Web

3. Vue 3.5 引入响应式优化

  • 链接https://blog.vuejs.org
  • 来源:Vue.js 官方
  • 摘要:响应式系统重写,大数组(10万+ 元素)渲染性能提升 5 倍。

4. Vite 6.0 发布,原生支持 RSC

  • 链接https://vite.dev
  • 来源:Vite 官方
  • 摘要:Vite 6.0 内置 React Server Components 支持,无需额外插件。

⚙️ 后端 / 架构

5. Kubernetes 1.31 引入 DRA(Dynamic Resource Allocation)GA

  • 链接https://kubernetes.io/blog
  • 来源:CNCF
  • 摘要:DRA 让 Pod 按需申请 GPU / FPGA / 网络资源,利用率提升 40%。

6. Deno 2.1 LTS 发布

  • 链接https://deno.com/blog
  • 来源:Deno 官方
  • 摘要:Deno 2.1 进入 LTS 阶段,承诺 5 年安全更新,npm 兼容性 100%。

🚀 独立开发 / OPC

7. GitHub Copilot Free 正式开放

  • 链接https://github.com/blog
  • 来源:GitHub
  • 摘要:免费用户每月 2000 次代码补全 + 50 次 Chat,对独立开发者是天降福音。

数据来源:HN / Dev.to / 各厂博客 采集时间:2026-07-03 09:00 (UTC+8)

📝

今日深度文

从单体到微服务:一家 5 人小团队的架构演进实录

一句话结论:5 人团队不要过早微服务,但当单体真的扛不住时,必须狠心拆分。

背景

我们团队是一个 5 人小公司,技术栈从 2024 年的 PHP 单体应用,经过 2 年逐步演进到 2026 年的 Go 微服务架构。

这篇文章不是"微服务最佳实践",而是"5 人团队在资源极度受限下的现实选择"。希望对同样处境的团队有参考。

演进时间线

2024-01  PHP 单体(5万行),MySQL 单库
   ↓ [QPS 100,单机够用]
2024-08  PHP 单体(8万行),单库扛不住查询
   ↓ [第一次拆分:读写分离]
2025-02  PHP 单体(10万行)+ Node.js 微服务(部分业务)
   ↓ [QPS 1000,PHP 进程开始频繁 OOM]
2025-10  Go 微服务(5 个服务)+ Kubernetes
   ↓ [QPS 5000,但运维成本爆炸]
2026-06  Go 微服务(12 个服务)+ Service Mesh
   当前状态:QPS 15000,团队 5 人 → 8 人

阶段 1:PHP 单体期(2024)

最初的架构非常简单:

[Nginx] → [PHP-FPM × 8] → [MySQL]

5 万行代码,单库单表,部署一台 4 核 8G 机器。

问题

  • 任意一个慢查询拖垮整个服务
  • 改一行代码需要全量回归
  • 5 个人共用一个代码库,merge conflict 每天 10+

但实际上对于 QPS 100 的初创业务,这个阶段完全没问题。我们犯的错误是"提前优化",花了 2 个月做了一个"未来需要"的抽象层,结果永远用不上。

阶段 2:读写分离(2024-08)

业务增长到 QPS 500,数据库开始报警。我们做的第一件事不是拆服务,而是只读读写分离

-- 主库负责写
CREATE USER 'app_write'@'%' IDENTIFIED BY 'xxx';
GRANT SELECT, INSERT, UPDATE, DELETE ON mydb.* TO 'app_write'@'%';

-- 从库负责读
CREATE USER 'app_read'@'%' IDENTIFIED BY 'xxx';
GRANT SELECT ON mydb.* TO 'app_read'@'%';

应用层改造:

// 写操作走主库
class UserRepository {
    public function findById($id) {
        // 读操作走从库
        return $this->readDb->table('users')->where('id', $id)->first();
    }
    
    public function create($data) {
        // 写操作走主库
        return $this->writeDb->table('users')->insert($data);
    }
}

收益

  • QPS 从 500 提升到 1500(读压力被分流)
  • 改造时间:1 周
  • 风险:低(主从延迟导致的"刚写就读不到"问题)

教训先做读写分离,再考虑拆服务。我们差点直接跳到微服务,幸亏刹住了。

阶段 3:第一个微服务(2025-02)

什么时候该拆微服务?我们用了三个判断条件:

  1. 业务独立(订单、支付、用户可以分开演进)
  2. 团队规模(5 人 + 不同业务线 owner)
  3. 技术栈需要(某些场景 Node.js 更适合,如实时通讯)

我们拆出了通知服务(Node.js + Socket.IO),独立部署:

[Nginx] → [PHP-FPM × 8] → [MySQL 主从]
              ↓ REST
       [Node.js 通知服务] → [Redis]

收益

  • 实时通知延迟从 5s 降到 100ms
  • PHP 单体体积减少 15%
  • 团队有了"多语言"经验

  • 第一个坑:服务间调用没做熔断。通知服务挂的时候,PHP 调用超时,拖垮了主服务
  • 第二个坑:没设计服务间认证。任何内网服务都能调通知服务,安全漏洞

阶段 4:Go 微服务 + K8s(2025-10)

QPS 到 5000,PHP 单体频繁 OOM。我们做了个大胆决定:PHP → Go 全量重写

新架构:

                  [Ingress]

       ┌──────────────┼──────────────┐
       ↓              ↓              ↓
   [API Gateway] → [Auth] → [User Service]
       ↓              ↓
   [Order]      [Payment] → [PostgreSQL]
       ↓              ↓
   [Inventory]   [Notification] → [Redis]

   [Analytics] → [ClickHouse]

   [K8s 集群 × 3]

技术选型

维度 选择 理由
语言 Go 性能好、静态编译、运维友好
框架 Gin 轻量、社区大
数据库 PostgreSQL 比 MySQL 更现代、JSON 支持好
缓存 Redis Cluster 7 个节点
消息队列 NATS JetStream 比 Kafka 轻,比 RabbitMQ 强
编排 Kubernetes 行业标准
Service Mesh Linkerd 比 Istio 轻 10 倍
监控 Prometheus + Grafana CNCF 标配

收益

  • QPS 提升到 5000(峰值 15000)
  • 内存占用降低 70%
  • 部署时间从 10 分钟降到 30 秒

阶段 5:踩过的 7 个坑

坑 1:服务拆分过细

最初我们拆了 12 个服务,结果 5 个人根本维护不过来:

# 反面教材
- user-service
- user-profile-service
- user-settings-service
- user-avatar-service
- user-notification-prefs-service
...

修正:合并到 3 个:user-serviceauth-serviceprofile-service

坑 2:分布式事务

跨服务的数据一致性是最难的问题。我们一开始用 2PC,发现性能太差;后来改用 Saga 模式:

// 订单创建的 Saga
func CreateOrderSaga(order Order) error {
    // Step 1: 创建订单(本地事务)
    if err := orderService.Create(order); err != nil {
        return err
    }
    
    // Step 2: 扣减库存(补偿:恢复库存)
    if err := inventoryService.Reserve(order.Items); err != nil {
        orderService.Cancel(order.ID)  // 补偿
        return err
    }
    
    // Step 3: 处理支付(补偿:退款)
    if err := paymentService.Charge(order); err != nil {
        inventoryService.Release(order.Items)  // 补偿
        orderService.Cancel(order.ID)
        return err
    }
    
    return nil
}

坑 3:服务发现

最初用硬编码 IP,重启就要改配置。后来改用 K8s Service + DNS:

# Kubernetes Service
apiVersion: v1
kind: Service
metadata:
  name: user-service
spec:
  selector:
    app: user-service
  ports:
    - port: 80
      targetPort: 8080

应用代码里直接用 http://user-service/user/123,DNS 自动负载均衡。

坑 4:可观测性

微服务出问题最可怕的是"不知道为什么挂了"。我们投入了 30% 的精力做可观测性:

  • Logging:Loki + Promtail
  • Tracing:Jaeger(OpenTelemetry 标准)
  • Metrics:Prometheus + Grafana
  • Alerting:AlertManager + PagerDuty
// OpenTelemetry 自动埋点
import "go.opentelemetry.io/otel"

func (s *OrderService) CreateOrder(ctx context.Context, order Order) error {
    tracer := otel.Tracer("order-service")
    ctx, span := tracer.Start(ctx, "CreateOrder")
    defer span.End()
    
    // 业务逻辑...
}

坑 5:数据库连接池

微服务场景下,每个服务都连数据库,连接数容易爆炸。我们用 PgBouncer 做连接池:

[Service] → [PgBouncer (连接池)] → [PostgreSQL]
默认:每个服务 10 个连接
PgBouncer:聚合 100 个连接为 20 个真实连接

坑 6:CI/CD 复杂度

12 个服务 × 3 个环境 = 36 套部署流水线。我们用 GitHub Actions + ArgoCD:

# .github/workflows/deploy.yml
name: Deploy
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build & Push Image
        run: docker build -t registry/user-service:${{ github.sha }} .
      - name: Update K8s Manifest
        run: |
          kubectl set image deployment/user-service \
            user-service=registry/user-service:${{ github.sha }}

坑 7:团队沟通成本

微服务最大的隐性成本是沟通成本。5 个人拆 12 个服务后,每个人的代码改动会影响多个团队。

修正:建立"服务 owner"机制 + 每周跨服务同步会。

现在的架构(2026-06)

经过一年调整,我们的稳定架构是 3 个核心服务 + 4 个辅助服务

服务 语言 QPS 团队 owner
user-service Go 8000 A
order-service Go 3000 B
payment-service Go 1500 C
notification-service Node.js 500 A
analytics-service Python 100 D
image-service Go 200 E
search-service Rust(实验) 50 D

我的看法

微服务不是越多越好,也不是越早越好。几个判断标准:

  1. 5 人以下不要微服务:单体 + 模块化就够了
  2. QPS < 1000 不要微服务:读写分离 + 缓存就够了
  3. 团队规模 / 服务数 ≤ 1.5:超过这个比例,沟通成本会爆炸
  4. 业务稳定后再拆:早期业务变化快,拆了反而是负担

参考


本文中的服务拆分、限流、连接池等代码模式均为工业界标准实践,可参考各组件官方文档实现。