0%

地大开源镜像站初步踩坑

中国地质大学开源镜像站在 13 年左右开始,在几年后因为没有人维护而荒废,在前两个月 站长 说希望能重启这个计划
于是启动了 cugsync,目前做完了基本雏形,暂时看起来运行正常,记录一些遇到的问题和解决方法

现在的方案很简单,后端 gin,前端 react,单机运行。
通过定时任务使用 rsync 从 清华大学开源软件镜像站 和 中国科学技术大学开源软件镜像站 进行数据的拉取,暂时仅提供校内网络访问
使用 caddy 代替 nginx 作为 web 服务器
使用 goaccess 进行访问以及流量分析

当前产品页面如下图

cug-mirror

rsync 命令

我们使用的命令例子如下

1
2
3
4
5
6
7
8
9
$ rsync -avz --delete --timeout=120 --ipv6 --safe-links rsync://site.com/xxx /machine/xxx

-a, --archive 归档模式,表示以递归方式传输文件,并保持所有文件属性,等于-rlptgoD
-v, --verbose 详细模式输出
-z, --compress 对备份的文件在传输时进行压缩处理
--delete 删除那些 DST 中 SRC 没有的文件
--timeout=TIME IP超时时间,单位为秒
-6, --ipv6 优先 IPv6
--safe-links 忽略指向 SRC 路径目录树以外的链接

rsync 卡死

在使用 rsync 命令的时候,通过将标准输出流重定向到文件,可以在镜像对应的文件日志中看到最近一次的同步信息(当然也可以在 rsync 命令后面指定 --log-file 来输出到文件)。
但在运行的过程出现了日志一直没有更新的情况,应该是 rsync 卡死了,使用 strace 进行排查,输入 strace -p PID 之后发现卡死在 select 上面

1
2
3
$ sudo strace -p 3089
strace: Process 3089 attached
select(5, [4], [], [4], {tv_sec=36, tv_usec=971296}

猜测可能是等待超时之后出现了啥问题,简单尝试了一下加入 timeout 参数,就解决这个问题

读写 broken

在调用同步的时候,我们使用 iscsi 进行存储,在日志中可以看到会出现 write broken 的情况

1
2
3
4
raspbian/pool/main/y/yt/python-yt_3.5.0-1_armhf.deb
rsync error: received SIGINT, SIGTERM, or SIGHUP (code 20) at rsync.c(644) [generator=3.1.3]
rsync error: received SIGINT, SIGTERM, or SIGHUP (code 20) at io.c(504) [receiver=3.1.3]
rsync: [receiver] write error: Broken pipe (32)

可能是因为存储不够稳定,加入重试机制,解决问题

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
28
for retryCount := 3; retryCount >= 0; retryCount-- {
// first time error, after 5 minutes retry
if err := rsync.ExecCommand(j.Config); err != nil && retryCount > 0 {
log.WithFields(log.Fields{
"retryCount": retryCount,
"err": err,
}).Infof("error, rsync job %s, spec: %s, config: %v", j.Name, j.Spec, j.Config)
<-time.After(5 * time.Minute)
} else if err != nil {
// job maybe failed
j.LatestSyncStatus = FAILED
RecordHistory(&History{
Name: j.Name,
StartTime: j.StartTime,
EndTime: time.Now(),
Info: err.Error(),
})
} else {
j.LatestSyncStatus = SUCC
RecordHistory(&History{
Name: j.Name,
StartTime: j.StartTime,
EndTime: time.Now(),
Info: "rsync complete",
})
break
}
}

超过最大连接数

在调用同步的时候,会在日志中看到超过最大连接数,应该是服务端返回的错误,日志内容如下,也通过重试解决

1
2
@ERROR: max connections (30) reached -- try again later
rsync error: error starting client-server protocol (code 5) at main.c(1657) [Receiver=3.1.3]

孤儿进程

在第一次排查卡死问题的时候,查看进程 rsync,突然发现居然有很多的进程,由于之前卡死,然后在 kill 掉主程序之后就被 init 接管变成了孤儿进程。可以使用下面命令同时结束进程和其子进程

1
$ kill -9 `ps -ef |grep PID|awk '{print $2}' `

orphan

顺便整理了孤儿进程和僵尸进程的内容,可以看 一个问题后总结孤儿进程和僵尸进程

参考资料

听说好看的人都关注了我的公众号《泫言》