1. 项目概述
SwiftChatSystem 是一个基于 C++ 开发的高性能社交平台后端系统,采用微服务架构设计,通过 gRPC 实现服务间通信。作为该系列博客的终篇,我们将重点讲解系统的部署实践,涵盖从本地运行到容器化部署的完整流程。
这个系统由多个独立服务组成,包括网关服务(GateSvr)、区域服务(ZoneSvr)以及各类业务服务(AuthSvr、OnlineSvr等)。每个服务都有明确的职责边界,通过定义良好的接口进行协作。部署这样的分布式系统需要考虑服务依赖、网络通信、数据持久化等多个维度的问题。
2. 系统架构与端口规划
2.1 服务组件与职责
系统包含以下核心服务组件:
- GateSvr:网关服务,处理客户端WebSocket连接,负责协议编解码和请求转发
- ZoneSvr:区域服务,协调各业务服务的调用,实现业务逻辑编排
- AuthSvr:认证服务,处理用户登录、注册等身份验证功能
- OnlineSvr:在线状态服务,管理用户在线状态信息
- FriendSvr:好友关系服务,处理好友添加、删除等社交关系
- ChatSvr:聊天服务,处理单聊和群聊消息
- FileSvr:文件服务,提供文件上传下载功能
2.2 端口规划与通信协议
各服务使用固定端口进行通信,具体规划如下:
| 服务名称 | gRPC端口 | 其他端口 | 协议说明 |
|---|---|---|---|
| GateSvr | 9091 | WebSocket 9090 | 客户端通过9090连接,内部服务通过9091调用 |
| ZoneSvr | 9092 | - | 仅提供gRPC接口,供GateSvr调用 |
| AuthSvr | 9094 | - | 认证相关gRPC接口 |
| OnlineSvr | 9095 | - | 在线状态gRPC接口 |
| FriendSvr | 9096 | - | 好友关系gRPC接口 |
| ChatSvr | 9098 | - | 聊天相关gRPC接口(含群组功能) |
| FileSvr | 9100 | HTTP 8080 | gRPC接口9100,文件下载HTTP接口8080 |
提示:端口规划时需考虑服务隔离和防火墙规则。生产环境中建议为不同服务配置不同的安全组策略。
2.3 服务依赖与启动顺序
系统服务之间存在明确的依赖关系:
- ZoneSvr 依赖所有业务服务(AuthSvr、OnlineSvr等)
- GateSvr 依赖 ZoneSvr
- 各业务服务之间无直接依赖
因此推荐的启动顺序为:
code复制AuthSvr → OnlineSvr → FriendSvr → ChatSvr → FileSvr → ZoneSvr → GateSvr
在实际部署时,可以通过健康检查机制确保上游服务就绪后再启动依赖服务,避免因服务未就绪导致的调用失败。
3. 本地环境部署
3.1 源码构建与准备
项目使用CMake构建系统,构建步骤如下:
bash复制# 克隆仓库
git clone https://github.com/YW8862/SwiftChatSystem.git
cd SwiftChatSystem
# 构建项目
./scripts/build-server.sh
# 或者使用make
make build
构建完成后,可执行文件位于build/backend/目录下,包括:
- authsvr
- onlinesvr
- friendsvr
- chatsvr
- filesvr
- zonesvr
- gatesvr
3.2 配置文件说明
每个服务都有对应的配置文件,例如authsvr.conf,采用JSON或INI格式,包含服务运行所需的基本参数。配置项支持通过环境变量覆盖,环境变量命名规则为{SERVICE_NAME}_{CONFIG_KEY},例如:
ini复制# authsvr.conf示例
[server]
port = 9094
log_level = info
[db]
path = ./data/auth
对应的环境变量为:
code复制AUTHSVR_SERVER_PORT=9094
AUTHSVR_SERVER_LOG_LEVEL=info
AUTHSVR_DB_PATH=./data/auth
3.3 本地运行步骤
在本地环境中,可以通过多个终端分别启动各服务:
bash复制# 终端1:启动认证服务
./build/backend/authsvr authsvr.conf
# 终端2:启动在线服务
./build/backend/onlinesvr onlinesvr.conf
# 终端3:启动好友服务
./build/backend/friendsvr friendsvr.conf
# 终端4:启动聊天服务
./build/backend/chatsvr chatsvr.conf
# 终端5:启动文件服务
./build/backend/filesvr filesvr.conf
# 终端6:启动区域服务(确保上述服务已启动)
./build/backend/zonesvr zonesvr.conf
# 终端7:启动网关服务(确保ZoneSvr已启动)
./build/backend/gatesvr gatesvr.conf
启动完成后,客户端可以通过ws://localhost:9090/ws连接到系统。
注意:本地运行模式下,各服务的RocksDB数据默认存储在
./data/目录下,请确保该目录有写入权限。生产环境建议使用绝对路径。
4. Docker Compose部署
4.1 Docker化准备
项目提供了Dockerfile和docker-compose.yml文件,位于deploy/docker/目录下。每个服务构建为独立的Docker镜像,通过build参数指定目标服务:
dockerfile复制# Dockerfile片段
ARG BUILD_TARGET
COPY . /app
WORKDIR /app
RUN ./scripts/build-server.sh ${BUILD_TARGET}
4.2 服务定义与配置
docker-compose.yml中定义了所有服务,示例配置如下:
yaml复制services:
authsvr:
image: swift/authsvr:latest
build:
context: .
dockerfile: deploy/docker/Dockerfile
args:
BUILD_TARGET: authsvr
ports:
- "9094:9094"
volumes:
- swift-data:/data
environment:
- AUTHSVR_SERVER_PORT=9094
- AUTHSVR_DB_PATH=/data/auth
其他服务配置类似,主要差异在于:
- 暴露的端口不同
- 挂载的卷路径可能不同
- 服务特定的环境变量配置
4.3 数据持久化方案
使用Docker命名卷实现数据持久化:
yaml复制volumes:
swift-data:
所有服务的持久化数据都存储在/data目录下,通过命名卷swift-data挂载。对于文件服务,可以单独挂载一个卷:
yaml复制filesvr:
volumes:
- swift-data:/data
- swift-files:/data/files
4.4 服务依赖与启动顺序
在docker-compose.yml中通过depends_on定义服务依赖:
yaml复制zonesvr:
depends_on:
- authsvr
- onlinesvr
- friendsvr
- chatsvr
- filesvr
gatesvr:
depends_on:
- zonesvr
注意:
depends_on仅控制容器启动顺序,不保证服务已就绪。实际部署时可结合健康检查确保服务可用性。
4.5 部署命令
在项目根目录执行以下命令进行部署:
bash复制# 构建所有镜像(可选)
./deploy/docker/build-all.sh
# 启动所有服务
docker compose -f deploy/docker-compose.yml up -d
# 查看日志
docker compose logs -f
5. Kubernetes部署(MiniKube)
5.1 环境准备
使用Minikube搭建本地K8s集群:
bash复制# 启动Minikube集群
minikube start --cpus=2 --memory=4096 --driver=docker
# 创建持久化目录
minikube ssh -- "sudo mkdir -p /data/swift-chat /data/swift-files && sudo chmod 777 /data/swift-chat /data/swift-files"
5.2 存储配置
定义PersistentVolume和PersistentVolumeClaim:
yaml复制# persistent-volume.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: swift-data-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /data/swift-chat
对应的PVC:
yaml复制apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: swift-data-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
5.3 配置集中管理
使用ConfigMap统一管理环境变量:
yaml复制# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: swift-config
data:
ZONESVR_AUTH_SVR_ADDR: "authsvr:9094"
ZONESVR_ONLINE_SVR_ADDR: "onlinesvr:9095"
GATESVR_ZONE_SVR_ADDR: "zonesvr:9092"
# 其他环境变量...
5.4 服务部署
每个服务对应一个Deployment和Service:
yaml复制# gatesvr-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: gatesvr
spec:
replicas: 1
selector:
matchLabels:
app: gatesvr
template:
metadata:
labels:
app: gatesvr
spec:
containers:
- name: gatesvr
image: swift/gatesvr:latest
ports:
- containerPort: 9090
- containerPort: 9091
envFrom:
- configMapRef:
name: swift-config
---
apiVersion: v1
kind: Service
metadata:
name: gatesvr
spec:
type: NodePort
selector:
app: gatesvr
ports:
- name: websocket
port: 9090
targetPort: 9090
nodePort: 30090
- name: grpc
port: 9091
targetPort: 9091
5.5 部署流程
完整部署步骤如下:
bash复制# 构建并加载镜像
./deploy/docker/build-all.sh
for s in authsvr onlinesvr friendsvr chatsvr filesvr zonesvr gatesvr; do
minikube image load swift/$s:latest
done
# 应用K8s配置
kubectl apply -k deploy/k8s
# 获取访问地址
minikube service -n master gatesvr --url
6. 配置与环境变量管理
6.1 配置优先级
系统配置遵循以下优先级:
- 环境变量
- 配置文件
- 代码默认值
建议生产环境将敏感信息(如密钥)通过环境变量注入,避免写入配置文件。
6.2 关键环境变量
各服务的关键环境变量:
ZoneSvr:
ZONESVR_AUTH_SVR_ADDR: 认证服务地址ZONESVR_SESSION_STORE_TYPE: 会话存储类型(memory/redis)ZONESVR_INTERNAL_SECRET: 内部通信密钥
GateSvr:
GATESVR_ZONE_SVR_ADDR: 区域服务地址GATESVR_ZONESVR_INTERNAL_SECRET: 与ZoneSvr一致的密钥
通用配置:
LOG_LEVEL: 日志级别(debug/info/warn/error)ROCKSDB_PATH: RocksDB存储路径HTTP_PORT: HTTP服务端口(如FileSvr)
7. 生产环境建议与扩展方向
7.1 存储方案扩展
当前使用RocksDB作为主要存储,可考虑以下扩展:
MySQL集成:
- 用户账号、好友关系等结构化数据迁移到MySQL
- 利用事务特性保证数据一致性
- 支持复杂查询需求
Redis集成:
- 会话状态、在线状态等高频访问数据存入Redis
- 利用Pub/Sub实现实时通知
- 提升系统横向扩展能力
MinIO对象存储:
- 文件服务支持MinIO作为存储后端
- 提升文件存储的可靠性和扩展性
- 配置文件存储类型切换:
ini复制[storage]
type = minio
endpoint = minio:9000
access_key = minioadmin
secret_key = minioadmin
bucket = swift-chat
7.2 可观测性增强
Prometheus监控:
- 各服务暴露metrics端点
- 配置ServiceMonitor自动采集指标
- 关键指标:请求量、延迟、错误率等
日志收集:
- 使用Fluentd或Filebeat收集容器日志
- 存入Elasticsearch集中管理
- 通过Kibana提供查询界面
7.3 自动扩缩容
HPA配置:
yaml复制apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: gatesvr-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: gatesvr
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
多区域部署:
- 使用K8s的拓扑分布约束
- 部署到多个可用区提升容灾能力
- 配置区域亲和性策略
8. 常见问题排查
8.1 服务启动失败
症状:服务启动后立即退出
排查步骤:
- 检查日志获取错误信息
- 验证配置文件路径和权限
- 确认依赖服务是否可用
- 检查端口是否被占用
- 验证数据目录可写
8.2 服务间通信问题
症状:服务间RPC调用失败
排查步骤:
- 确认服务发现配置正确(地址、端口)
- 检查网络连通性(netcat/telnet测试)
- 验证gRPC健康状态
- 检查防火墙/安全组规则
- 确认协议版本兼容性
8.3 性能问题
症状:系统响应慢,吞吐量低
优化方向:
- 调整gRPC通道参数(连接池大小、超时等)
- 优化RocksDB配置(缓存大小、压缩等)
- 增加服务实例数
- 分析热点数据考虑缓存
- 检查系统资源瓶颈(CPU、内存、IO)
9. 部署架构演进路线
随着业务增长,部署架构可以按以下路线演进:
- 单机部署:开发测试环境,所有服务部署在同一节点
- 容器化部署:使用Docker Compose,服务隔离,便于开发协作
- K8s集群部署:生产环境,具备弹性伸缩能力
- 多集群部署:跨区域部署,提升容灾能力
- 服务网格集成:引入Istio等服务网格,增强流量管理
每个阶段都可以平滑过渡,关键是要在架构设计时预留扩展点,如:
- 服务发现抽象
- 配置中心集成
- 可观测性接口
- 存储插件机制