topic: architecture

微服务架构初探

2023 年下半年,公司决定把单体应用拆了。

理由:

  • 代码量太大,编译一次 10 分钟
  • 团队 20 个人,改代码经常冲突
  • 故障影响范围太大,一个模块挂全站挂

我负责其中一个模块的拆分。

为什么是微服务

单体的问题

1
2
3
用户模块 → 订单模块 → 支付模块 → 通知模块
↓ ↓ ↓ ↓
MySQL MySQL MySQL MySQL
  • 编译慢
  • 部署风险高
  • 扩展困难
  • 技术栈绑定

微服务的优势

1
2
3
用户服务  订单服务  支付服务  通知服务
↓ ↓ ↓ ↓
用户库 订单库 支付库 通知库
  • 独立部署
  • 独立扩展
  • 技术异构
  • 故障隔离

拆分思路

1. 按业务拆分

1
2
3
4
用户域:用户、认证、授权
订单域:订单、购物车
支付域:支付、退款
通知域:短信、邮件、推送

2. 数据库拆分

每个服务有自己的数据库:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-- 用户服务
CREATE TABLE users (
id BIGINT PRIMARY KEY,
username VARCHAR(50),
password_hash VARCHAR(255),
created_at TIMESTAMP
);

-- 订单服务
CREATE TABLE orders (
id BIGINT PRIMARY KEY,
user_id BIGINT,
amount DECIMAL(10,2),
status VARCHAR(20),
created_at TIMESTAMP
);

3. API 通信

  • HTTP/REST:简单,适合同步调用
  • gRPC:性能高,适合内部调用
  • 消息队列:异步,解耦
1
2
3
4
5
6
7
8
9
10
# 用户服务(REST)
@app.get("/users/{user_id}")
def get_user(user_id: int):
return {"id": user_id, "username": "xxx"}

# 订单服务调用
import requests
def get_order_user(user_id):
resp = requests.get(f"http://user-service/users/{user_id}")
return resp.json()

服务治理

1. 服务注册与发现

1
2
3
4
5
6
# Nacos / Consul / Eureka
services:
user-service:
ip: 10.0.0.1
port: 8080
health: /health

2. 配置中心

1
2
3
4
# Apollo / Nacos Config
spring:
config:
import: optional:nacos:${spring.application.name}.yml

3. 熔断限流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from prometheus_client import Counter, Histogram
import time

# 监控
request_duration = Histogram('request_duration_seconds', 'Request duration')
request_count = Counter('request_total', 'Total requests')

@app.middleware("http")
async def monitor(request, call_next):
start = time.time()
response = await call_next(request)
request_duration.observe(time.time() - start)
request_count.inc()
return response

4. 网关

1
2
3
4
5
6
7
8
9
10
# Kong / Spring Cloud Gateway
location /api/ {
proxy_pass http://backend;

# 限流
limit_req zone=api_limit burst=10 nodelay;

# 认证
auth_request /auth;
}

遇到的问题

1. 分布式事务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 场景:下单成功,扣库存失败
# 方案:TCC / Saga / 消息最终一致

# Saga 模式
def create_order():
# 1. 创建订单(待确认)
order = create_order_pending()

# 2. 扣库存
try:
deduct_inventory(order.items)
except:
# 失败,撤销订单
cancel_order(order.id)
raise

# 3. 扣款
try:
deduct_balance(order.user_id, order.amount)
except:
# 失败,归还库存
restore_inventory(order.items)
cancel_order(order.id)
raise

# 4. 确认订单
confirm_order(order.id)

2. 服务间调用延迟

  • 尽量用异步
  • 批量操作
  • 本地缓存

3. 运维复杂度

  • 日志聚合:ELK / Loki
  • 链路追踪:Jaeger / SkyWalking
  • 监控:Prometheus + Grafana

技术栈

角色 技术
网关 Kong / Spring Cloud Gateway
注册中心 Nacos
配置中心 Nacos
熔断 Sentinel
消息队列 RabbitMQ / Kafka
数据库 MySQL + ShardingSphere
缓存 Redis Cluster
容器 Docker + K8s
CI/CD GitLab CI

总结

微服务不是银弹。

优点:

  • 独立部署
  • 故障隔离
  • 技术灵活

缺点:

  • 复杂度高
  • 运维成本高
  • 分布式问题

适合:

  • 大团队
  • 复杂业务
  • 需要快速迭代

目前还在探索中,后续有进展再更新。