今天来聊聊我们在构建企业级短信平台时的一些架构设计心得。短信服务看似简单,但要在高并发场景下保证稳定性、可观测性和可扩展性,背后的技术选型与架构设计才是关键。
一、总体介绍
1.1 解决的问题
在短信业务中,我们面临几个核心挑战:
- 高并发写入:营销活动期间,短时间内可能有数万条短信发送请求涌入
- 实时性与可靠性的平衡:用户希望短信立即发出,但下游通道往往有速率限制
- 多维度统计:需要实时统计发送量、成功率、计费信息
- 风控合规:黑名单过滤、敏感词检测必须在发送前完成
1.2 在平台中的位置
本文介绍的架构设计是整个短信平台的"中枢神经",位于 API 接入层与下游通道之间,承担着请求调度、异步处理、数据持久化的核心职责。
1.3 核心价值
通过"分层架构 + Worker 异步处理"的设计,我们实现了:
- 解耦:API 层只负责接收请求,具体处理交给 Worker
- 削峰:利用队列缓冲突发流量
- 可扩展:Worker 可以水平扩容
- 可观测:每个组件都有独立的日志输出
二、技术要点
2.1 三层架构设计
我们的平台采用经典的三层架构:
┌─────────────────────────────────────────────────────────────┐
│ 前端 (Vue 3) │
│ customer-web - Vben Admin 框架 │
└───────────────────────────┬─────────────────────────────────┘
│
┌───────────────────────────▼─────────────────────────────────┐
│ Nginx 反向代理 │
└───────────────┬───────────────────────────┬─────────────────┘
│ │
┌───────────────▼───────────┐ ┌───────────▼─────────────────┐
│ Django 管理后台 │ │ Go API 服务 │
│ (ladmin) │ │ (lsms-api) │
│ - 用户管理 │ │ - 短信发送 API │
│ - 模板/签名审核 │ │ - 调度器 │
│ - 充值管理 │ │ - Worker 集群 │
│ - 统计报表 │ │ - 计费 Worker │
│ │ │ - 统计 Worker │
│ │ │ - 黑名单 Worker │
└───────────────┬───────────┘ └───────────┬─────────────────┘
│ │
┌───────────────▼───────────────────────────▼─────────────────┐
│ PostgreSQL + Redis │
│ 数据持久化 + 缓存/队列 │
└─────────────────────────────────────────────────────────────┘技术选型考量:
- Vue 3 + Vben Admin:现代化前端生态,组件丰富,适合构建复杂的运营后台
- Django:成熟的企业级后台框架,自带 Admin 界面,适合快速开发管理功能
- Go API 服务:高并发、低延迟,适合短信发送这类 IO 密集型场景
- PostgreSQL:ACID 事务、JSONB 支持,适合存储复杂的业务数据
- Redis:高性能缓存与队列,支撑高并发与解耦
2.2 Worker 异步处理机制
Worker 是我们架构的核心创新点。当 API 接收到发送请求后,不会立即处理,而是:
- 写入队列:将任务推入 Redis 队列
- 记录日志:在 PostgreSQL 中创建发送记录
- 异步处理:多个 Worker 从队列中拉取任务并行处理
flowchart TD
Start(["接收发送请求"]) --> Validate["校验签名/限流/鉴权"]
Validate --> Enqueue["写入发送队列(Redis)"]
Enqueue --> Record["记录发送记录(PostgreSQL)"]
Record --> Dispatch["调度器分发任务"]
Dispatch --> Billing["计费 Worker 处理"]
Dispatch --> Stats["统计 Worker 处理"]
Dispatch --> Blacklist["黑名单过滤 Worker 处理"]
Billing --> Update["更新计费/余额"]
Stats --> UpdateStats["更新统计指标"]
Blacklist --> FilterOK{"命中黑名单?"}
FilterOK --> |是| Drop["丢弃/标记失败"]
FilterOK --> |否| Send["下发到通道"]
Send --> Done(["完成"])
Drop --> Done
Update --> Done
UpdateStats --> DoneWorker 类型说明:
| Worker 类型 | 职责 | 配置参数 |
|---|---|---|
| 调度 Worker | 扫描定时任务、分发消息 | dispatcher_count: 2 |
| 计费 Worker | 计算费用、扣减余额 | worker_count: 2, batch_size: 500 |
| 统计 Worker | 汇总发送数据、生成报表 | scan_interval: 60s, batch_size: 1000 |
| 黑名单 Worker | 过滤黑名单号码 | worker_count: 4, cache_ttl: 600s |
2.3 Nginx 反向代理与负载均衡
Nginx 作为入口网关,承担着流量分发、SSL 终止、静态资源缓存等职责:
server {
listen 443 ssl;
server_name sms.hongboxinhua.com;
# API requests proxy to ladmin backend
location /basic-api/ {
proxy_pass http://172.17.0.1:3038/api/v1/customer/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Increase buffer sizes for API responses
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
}
# Static files caching
location ~* \.(css|js)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}关键配置解析:
proxy_buffer_size:增大缓冲区,避免大响应被截断expires 1y:静态资源长期缓存,减轻服务器压力X-Forwarded-For:传递真实客户端 IP,便于后端限流统计
2.4 限流与安全防护
我们在 Django 和 Go API 两层都实现了限流:
# Django REST Framework 限流配置
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_RATES': {
'anon': '100/minute',
'user': '1000/minute',
'login': '5/minute',
'register': '3/minute',
'send_code': '1/minute',
'customer_api': '60/minute',
'sms_api': '30/minute',
},
}限流策略根据接口类型差异化设置:登录注册类接口严格限流,防止暴力破解;短信发送接口限流较宽松,但仍有上限保护。
三、核心代码片段
3.1 Go API 服务配置
# config.yaml - 服务核心配置
server:
host: "0.0.0.0"
port: 8080
mode: "debug"
database:
host: "127.0.0.1"
port: 5432
user: "postgres"
password: "***"
dbname: "lesms"
max_open_conns: 100
max_idle_conns: 10
redis:
host: "localhost"
port: 6379
db: 6
pool_size: 100
min_idle_conns: 10
# Worker 配置
worker:
dispatcher_count: 2
queue_timeout: 5
schedule_scan_interval: 10
billing:
worker_count: 2
batch_size: 500
scan_interval: 300
stats:
batch_size: 1000
scan_interval: 60
blacklist:
worker_count: 4
cache_ttl: 600配置说明:
max_open_conns: 100:数据库连接池大小,避免连接耗尽batch_size:Worker 批量处理数量,平衡吞吐与延迟cache_ttl: 600:黑名单缓存 10 分钟,减少数据库查询
3.2 日志轮转配置
log:
level: "debug"
dir: "logs"
max_size: 100 # 单个日志文件最大 100MB
max_backups: 30 # 保留 30 个历史文件
max_age: 7 # 保留 7 天
compress: true # 压缩旧日志每个组件都有独立的日志文件:
lsms-api.log- API 服务日志dispatcher.log- 调度 Worker 日志billing.log- 计费 Worker 日志stats.log- 统计 Worker 日志blacklist.log- 黑名单 Worker 日志
【放一张日志目录结构截图】
3.3 数据库连接池配置
# Django 数据库配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'lesms',
'USER': 'postgres',
'PASSWORD': '***',
'HOST': '127.0.0.1',
'PORT': '5432',
}
}四、实际效果
通过这套架构,我们在生产环境实现了:
- 峰值处理能力:单机可处理 5000+ TPS 的发送请求
- 平均延迟:从请求接收到入队 < 50ms
- 系统可用性:99.9%(过去 6 个月数据)
- 故障隔离:单个 Worker 故障不影响整体服务

五、总结与展望
本文介绍了短信通道管理平台的核心架构设计,重点包括:
- 三层架构:前端 + Django 后台 + Go API 服务,职责清晰
- Worker 异步处理:解耦、削峰、可扩展
- 完善的可观测性:多维度日志、监控大盘
- 安全防护:多层限流、黑名单过滤
后续文章我们将深入探讨:
- 短信通道的智能路由与故障转移
- 黑名单系统的设计与优化
- 高并发场景下的数据库优化实践
评论 (0)