负载均衡集群环境下的代码同步实现方案
背景说明
项目部署在腾讯云服务器上,由于云环境使用Linux Container技术,远程登录需要通过代理,且服务器无法直接访问外部网络。因此放弃了搭建SVN版本控制系统的方案。
核心需求
- 将同一份代码同时同步到多台服务器
- 确保各服务器能在极短时间内完成同步
- 服务器处于同一内网环境,内网传输速率较高,服务器数量不多时带宽不是瓶颈
问题与解决方案
问题一:无密码SSH同步
rsync是常用的同步工具,支持增量同步。直接使用需要每次输入密码,通过SSH的证书认证可以解决此问题。
密钥生成与配置步骤:
首先生成SSH密钥对:
# 生成密钥对,可设置密码或留空
ssh-keygen -f ~/.ssh/deploy_key
# 将公钥分发到目标服务器
ssh-copy-id -i ~/.ssh/deploy_key.pub deploy_user@target_server_ip
# 添加到SSH代理
eval `ssh-agent -s`
ssh-add ~/.ssh/deploy_key
关于ssh-agent的使用,需要注意以下几点:
- 执行
eval `ssh-agent -s`初始化代理会话 - 可以使用keychain工具简化证书管理
- 在~/.bash_profile中添加keychain配置实现会话保持
# ~/.bash_profile 配置示例
keychain ~/.ssh/deploy_key
. ~/.keychain/$HOSTNAME-sh
如需每次登录重新验证证书,可使用keychain --clear清除缓存。
问题二:多服务器并行同步
bash脚本默认单线程执行,利用后台符号&可实现多任务并行。以下是同步脚本的实现:
#!/usr/bin/env bash
# 加载服务器配置
source server_list.conf
# 源代码目录
SOURCE_PATH='/data/wwwroot'
# 目标服务器目录
TARGET_PATH='/data/'
# rsync同步参数
RSYNC_ARGS='-avz --progress --exclude=*.log --exclude=runtime/'
# 执行并行同步
for host in ${SERVER_IPS}
do
{
sync_cmd="rsync ${RSYNC_ARGS} ${SOURCE_PATH} ${DEPLOY_USER}@${host}:${TARGET_PATH}"
echo "开始同步: ${host}"
${sync_cmd} >> ${LOG_FILE} 2>&1
echo "完成同步: ${host}"
} &
done
# 等待所有后台任务完成
wait
echo "所有服务器同步完成"
通过在循环体结尾添加&符号,所有rsync命令会同时发起执行,有效降低多台服务器间的同步时间差。
问题三:脚本扩展性设计
将服务器列表抽取为独立配置文件,便于维护:
# server_list.conf
# 检查并启动ssh-agent
check_agent=`ps aux | grep ssh-agent | grep -v grep`
if [ -z "${check_agent}" ]; then
eval `ssh-agent -s`
keychain --clear
fi
ssh-add ~/.ssh/deploy_key
# 服务器IP地址列表
SERVER_IPS='192.168.1.10 192.168.1.11 192.168.1.12'
# 部署用户
DEPLOY_USER='deploy'
# 日志目录
LOG_DIR='./sync.log'
# 记录同步时间
echo "=== 同步开始: $(date) ===" >> ${LOG_DIR}
当集群规模变化时,只需修改配置文件中的IP列表即可,无需调整脚本逻辑。
其他可行方案
方案一:建立中转同步目录
建议在每台目标服务器上预先创建专门的同步目录,脚本先将代码同步至中转目录,再由本地脚本从该目录同步至实际运行目录。
方案二:共享存储方案
利用Linux autofs自动挂载技术,让所有应用服务器共享同一存储卷,代码文件只存储一份。但需注意此方案会削弱负载均衡的容错能力——当存储服务器故障时,整个集群将不可用。
各方案均有优劣,需根据实际业务场景权衡选择。
