适用人群:有后端开发经验的开发者
学习时长:约2-3天(每天3小时)
重要程度:★★★☆☆(进阶必学)
一、微服务是什么?
微服务是一种架构风格,将应用拆分为一组小型、独立部署的服务,每个服务运行在自己的进程中。
| 对比项 | 单体架构 | 微服务架构 |
|---|---|---|
| 部署 | 整体部署 | 独立部署 |
| 技术栈 | 统一 | 可以不同 |
| 扩展 | 整体扩展 | 按需扩展 |
| 复杂度 | 代码复杂 | 运维复杂 |
| 适用场景 | 小型项目 | 大型项目 |
二、微服务核心组件
┌─────────────────────────────────────────────────────────┐
│ 客户端(Web/APP) │
└─────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ API 网关(Gateway) │
│ 路由、限流、认证、日志 │
└─────────────────────────┬───────────────────────────────┘
│
┌─────────────────┼─────────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 用户服务 │ │ 订单服务 │ │ 商品服务 │
│ (User) │ │ (Order) │ │ (Product) │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 用户数据库 │ │ 订单数据库 │ │ 商品数据库 │
└──────────────┘ └──────────────┘ └──────────────┘
三、API 网关
3.1 网关职责
✅ 路由转发:将请求转发到对应服务
✅ 负载均衡:分发流量到多个实例
✅ 认证授权:统一身份验证
✅ 限流熔断:保护后端服务
✅ 日志监控:记录请求日志
✅ 协议转换:HTTP ↔ gRPC
3.2 常用网关
| 网关 | 语言 | 特点 |
|---|---|---|
| Kong | Lua | 功能最全、插件丰富 |
| APISIX | Lua | 高性能、国产 |
| Spring Cloud Gateway | Java | Spring生态 |
| Nginx | C | 轻量级、高性能 |
| Traefik | Go | 云原生、自动发现 |
3.3 Nginx 作为网关
# 微服务网关配置
upstream user-service {
server 192.168.1.10:8081;
server 192.168.1.11:8081;
}
upstream order-service {
server 192.168.1.20:8082;
server 192.168.1.21:8082;
}
upstream product-service {
server 192.168.1.30:8083;
}
server {
listen 80;
server_name api.example.com;
# 用户服务
location /api/users/ {
proxy_pass http://user-service;
proxy_set_header X-Request-ID $request_id;
}
# 订单服务
location /api/orders/ {
proxy_pass http://order-service;
proxy_set_header X-Request-ID $request_id;
}
# 商品服务
location /api/products/ {
proxy_pass http://product-service;
proxy_set_header X-Request-ID $request_id;
}
# 限流
limit_req_zone $binary_remote_addr zone=api:10m rate=100r/s;
location /api/ {
limit_req zone=api burst=200 nodelay;
}
}
四、服务间通信
4.1 同步通信(HTTP/gRPC)
// Go - HTTP调用其他服务
func getUserFromService(userId int) (*User, error) {
resp, err := http.Get(fmt.Sprintf("http://user-service/api/users/%d", userId))
if err != nil {
return nil, err
}
defer resp.Body.Close()
var user User
json.NewDecoder(resp.Body).Decode(&user)
return &user, nil
}
// Go - gRPC调用(更高效)
// 需要定义.proto文件,生成代码后调用
4.2 异步通信(消息队列)
# Python - RabbitMQ
import pika
# 生产者
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.queue_declare(queue='order_created')
channel.basic_publish(
exchange='',
routing_key='order_created',
body=json.dumps({'order_id': 123, 'user_id': 456})
)
connection.close()
# 消费者
def callback(ch, method, properties, body):
data = json.loads(body)
print(f"收到订单:{data}")
# 处理订单...
channel.basic_consume(queue='order_created', on_message_callback=callback)
channel.start_consuming()
// Node.js - Redis消息队列
const Redis = require('ioredis')
const redis = new Redis()
// 发布消息
await redis.publish('order:created', JSON.stringify({
orderId: 123,
userId: 456
}))
// 订阅消息
redis.subscribe('order:created')
redis.on('message', (channel, message) => {
const data = JSON.parse(message)
console.log('收到消息:', data)
})
五、服务注册与发现
5.1 Consul
# 安装Consul
docker run -d --name consul -p 8500:8500 consul:latest
# 服务注册(HTTP API)
curl -X PUT http://localhost:8500/v1/agent/service/register -d '{
"ID": "user-service-1",
"Name": "user-service",
"Tags": ["v1"],
"Address": "192.168.1.10",
"Port": 8081,
"Check": {
"HTTP": "http://192.168.1.10:8081/health",
"Interval": "10s"
}
}'
# 服务发现
curl http://localhost:8500/v1/catalog/service/user-service
5.2 etcd(K8S使用)
// Go - etcd服务注册
cli, _ := clientv3.New(clientv3.Config{
Endpoints: []string{"localhost:2379"},
})
// 注册服务
cli.Put(context.Background(), "/services/user-service/instance-1",
"192.168.1.10:8081",
clientv3.WithLease(lease.ID))
// 发现服务
resp, _ := cli.Get(context.Background(), "/services/user-service/",
clientv3.WithPrefix())
六、熔断与限流
6.1 熔断器模式
// Go - 使用gobreaker
import "github.com/sony/gobreaker"
cb := gobreaker.NewCircuitBreaker(gobreaker.Settings{
Name: "user-service",
MaxRequests: 3,
Interval: 10 * time.Second,
Timeout: 30 * time.Second,
ReadyToTrip: func(counts gobreaker.Counts) bool {
return counts.ConsecutiveFailures > 5
},
})
// 使用熔断器
result, err := cb.Execute(func() (interface{}, error) {
return getUserFromService(userId)
})
6.2 限流
// Go - 令牌桶限流
import "golang.org/x/time/rate"
// 每秒100个请求,突发200
limiter := rate.NewLimiter(100, 200)
func handler(w http.ResponseWriter, r *http.Request) {
if !limiter.Allow() {
http.Error(w, "Too Many Requests", http.StatusTooManyRequests)
return
}
// 处理请求
}
# Nginx限流
limit_req_zone $binary_remote_addr zone=api:10m rate=100r/s;
server {
location /api/ {
limit_req zone=api burst=200 nodelay;
proxy_pass http://backend;
}
}
七、Docker Compose 微服务编排
version: '3.8'
services:
# API网关
gateway:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx/gateway.conf:/etc/nginx/nginx.conf
depends_on:
- user-service
- order-service
- product-service
# 用户服务
user-service:
build: ./services/user
environment:
- DATABASE_URL=mysql://root:password@user-db:3306/user_db
- REDIS_URL=redis://redis:6379/0
depends_on:
- user-db
- redis
# 订单服务
order-service:
build: ./services/order
environment:
- DATABASE_URL=mysql://root:password@order-db:3306/order_db
- RABBITMQ_URL=amqp://guest:guest@rabbitmq:5672
depends_on:
- order-db
- rabbitmq
# 商品服务
product-service:
build: ./services/product
environment:
- DATABASE_URL=mysql://root:password@product-db:3306/product_db
depends_on:
- product-db
# 数据库
user-db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: user_db
volumes:
- user_db_data:/var/lib/mysql
order-db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: order_db
volumes:
- order_db_data:/var/lib/mysql
product-db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: product_db
volumes:
- product_db_data:/var/lib/mysql
# 消息队列
rabbitmq:
image: rabbitmq:3-management
ports:
- "5672:5672"
- "15672:15672"
# 缓存
redis:
image: redis:7-alpine
ports:
- "6379:6379"
# 服务发现(可选)
consul:
image: consul:latest
ports:
- "8500:8500"
volumes:
user_db_data:
order_db_data:
product_db_data:
八、微服务最佳实践
✅ 服务拆分:按业务领域拆分(用户、订单、商品)
✅ 数据库独立:每个服务有自己的数据库
✅ API网关:统一入口,处理认证、限流
✅ 服务注册发现:Consul/etcd/Nacos
✅ 配置中心:统一管理配置
✅ 链路追踪:Jaeger/Zipkin
✅ 日志聚合:ELK Stack
✅ 监控告警:Prometheus + Grafana
✅ 熔断限流:Hystrix/Resilience4j
✅ 容器化部署:Docker + Kubernetes
九、何时使用微服务
适合微服务
✅ 团队规模大(>10人)
✅ 业务复杂度高
✅ 需要独立部署和扩展
✅ 技术栈多样化需求
✅ 高可用性要求
不适合微服务
❌ 小型项目
❌ 团队规模小(<5人)
❌ 业务简单
❌ 运维能力不足
❌ 初创公司快速迭代
学习建议
- 先理解单体架构的痛点,才能理解微服务的价值
- 从简单的服务拆分开始,不要一开始就过度设计
- 掌握Docker和Docker Compose,这是微服务的基础
- 学习API网关配置,统一入口是关键
- 了解服务间通信,同步(HTTP/gRPC)和异步(消息队列)
下一步学习
- Kubernetes — 容器编排
- Istio — 服务网格
- Spring Cloud — Java微服务全家桶