寻找方便的在线更新 service 程序的方案

2022-03-05 12:32:52 +08:00
 seakingii

说下需求:

我的服务器上运行着十几个 service,是用 c#和 GO 写的可执行文件,当前用 supervisor 来管理,目前更新 service 我是先在 supervisor 里停止它,然后用 FTP 上传新的可执行文件,上传完成后在 supervisor 里启动它.

如果偶尔更新,这样操作问题不大,现在的问题是经常要更新多个 service,感觉这样效率太低.

有没有这种方案: 1 上传新的可执行文件时不需要在 supervisor 先停止 service 2 上传完成后 service 会自动重启 3 不太需要优雅的"不中断服务更新",短时间停止一下问题不大.

如果能用 supervisor 实现最好,其它的也可以考虑.

不熟悉 linux 运营这块,请指点...

2329 次点击
所在节点    程序员
22 条回复
FrankAdler
2022-03-05 12:52:41 +08:00
用 systemd 代理 supervisor ,语法更简单,ftp 建议换成脚本
go build xxx
scp xx oot@1.2.3.4:/xxx
ssh root@1.2.3.4 "
tar ...
mv ...
rm ...
systemctl restart xxx
....
"
echo "手工"
brader
2022-03-05 15:17:58 +08:00
简单搞得话很容易,你可以使用 git 仓库来存储代码,然后你在服务器起一个定时任务,写个 shell ,1 分钟拉取一次 git 代码,判断 git 代码有更新,就执行 build 和重启命令。
liuhan907
2022-03-05 15:46:19 +08:00
如果你不抗拒新东西的话,弄个单节点 k8s ,比方说 k3s 这种轻量发行版,然后每次发版本打个新镜像往 k8s 一丢就了事了。
ch2
2022-03-05 15:57:04 +08:00
这是一个示例脚本:
CGO_ENABLED=0 go build -o my_service -a -ldflags '-extldflags "-static"' .
scp service root@x.x.x.x:/root/my_service
ssh root@x.x.x.x "bash /root/update_service.sh"
其中在部署机器上的 /root/update_service.sh 内容为:
systemctl stop my_service
rm -rf /usr/local/bin/my_service
cp my_service /usr/local/bin
chmod +x /usr/local/bin/my_service
systemctl start my_service
此外需要在编译的机器上添加待部署机器上的 ssh 私钥,以及在待部署机器上写 systemctl 的 my_service.service 文件
gesse
2022-03-05 17:37:07 +08:00
[program:bin]
command=/opt/bin

$ mv /opt/bin /tmp/
$ mv ~/newbin /opt/bin

$ supervisorctl restart bin


linux 文件占用是用的 inode ,而非路径,所以可以把正在执行的文件 move 到其他目录,然后把新版本的执行文件 mv 到正确目录,然后 restart
gesse
2022-03-05 17:39:22 +08:00
如果是十多个 supervisor 服务, 完全可以把执行文件放到一个目录里, 然后替换目录

再一次性
$ supervisorctl reload
codehz
2022-03-05 17:40:16 +08:00
虽然 linux 不允许覆盖正在运行的程序,但是你可以先删除了再上传同名文件(
crackhopper
2022-03-05 18:06:23 +08:00
显然用 k8s 更容易搞定。搞很多脚本,脚本维护也是问题。后续系统继续扩展也是问题。
ClericPy
2022-03-05 18:15:27 +08:00
以为挺常见的场景, 结果楼上给的都不是我常见的...

gunicorn gracefully restart - Google 搜索 - https://www.google.com/search?q=gunicorn+gracefully+restart&oq=gunicorn+gracefully+restart&aqs=chrome..69i57.7670j0j7&sourceid=chrome&ie=UTF-8

搜索关键词主要就是 gracefully restart, 可以参考上面 gunicorn 通过 HUP 信号做的那种

以前也见过 nginx 切换流量的做法, 反代指向的本地服务多个版本是多个进程实例和端口的, 这种也是不宕机直接切换流量的路子

如果其他的云原生那边的就不提了, 饿了吃饭去了
EminemW
2022-03-05 18:29:01 +08:00
jenkins 写脚本
hongzx
2022-03-05 18:56:49 +08:00
用 docker 来运行
Git+Drone 自动化部署
vvhhaaattt
2022-03-05 19:07:12 +08:00
ansible 没人提么?我们之前 supervisor 管理 python 跟 golang ,都用 supervisor 发布。
vvhhaaattt
2022-03-05 19:07:35 +08:00
@vvhhaaattt ansible 发布……
ragnaroks
2022-03-05 21:00:58 +08:00
docker
cosmtrek
2022-03-05 21:26:30 +08:00
k8s +1
kirile
2022-03-05 21:53:09 +08:00
我是自己用 go 写了个程序, 负责服务停止, 替换, 服务启动, 监听一个 rpc 服务用来接收需要替换的文件压缩包, 把多个服务的路径什么的维护起来. 然后配合 WinForm 客户端, 更新服务的时候就基本上两步就行, 选择服务->点击部署. 另外 WinSCP 可以支持即使 systemd 服务运行着也照样替换 golang 可执行文件, 这个的话也挺方便, 找到目录->拖拽覆盖->重启服务
xuanbg
2022-03-06 08:20:52 +08:00
Jenkins 装一个,每个 service 配一个 job 。哪个有更新点一下哪个 job 的构建就完事。
Dogtler
2022-03-06 09:26:50 +08:00
K8s 滚动更新
shoaly
2022-03-06 10:47:31 +08:00
如果是我来做这个方案的话:
1 做一个 http 的中心化软件下载地址
2 做一个脚本 , 通过 cron 定期从中心化节点下载文件(假设为 xxx), 并且命名为 xxx.update (这一步通过 cron 做更稳定无脑)
3 另一个脚本检查 xxx.update 和 本地 xxx md5 是否一致, 如果不一致就删除 xxx , 然后将 xxx.update 修改为 xxx, 并且运行重启脚本: pkill xxx && chmod+x xxx && nohup ./xxx &
4 如果 md5 一致, 就删除 xxx.update
sampeng
2022-03-06 14:20:01 +08:00
= =!这不就是 docker-composer 干的事么。。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/838157

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX