V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
seakingii
V2EX  ›  程序员

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

  •  
  •   seakingii · Mar 5, 2022 · 3138 views
    This topic created in 1520 days ago, the information mentioned may be changed or developed.

    说下需求:

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

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

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

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

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

    22 replies    2022-03-06 17:49:09 +08:00
    FrankAdler
        1
    FrankAdler  
       Mar 5, 2022
    用 systemd 代理 supervisor ,语法更简单,ftp 建议换成脚本
    go build xxx
    scp xx [email protected]:/xxx
    ssh [email protected] "
    tar ...
    mv ...
    rm ...
    systemctl restart xxx
    ....
    "
    echo "手工"
    brader
        2
    brader  
       Mar 5, 2022
    简单搞得话很容易,你可以使用 git 仓库来存储代码,然后你在服务器起一个定时任务,写个 shell ,1 分钟拉取一次 git 代码,判断 git 代码有更新,就执行 build 和重启命令。
    liuhan907
        3
    liuhan907  
       Mar 5, 2022
    如果你不抗拒新东西的话,弄个单节点 k8s ,比方说 k3s 这种轻量发行版,然后每次发版本打个新镜像往 k8s 一丢就了事了。
    ch2
        4
    ch2  
       Mar 5, 2022
    这是一个示例脚本:
    CGO_ENABLED=0 go build -o my_service -a -ldflags '-extldflags "-static"' .
    scp service [email protected]:/root/my_service
    ssh [email protected] "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
        5
    gesse  
       Mar 5, 2022
    [program:bin]
    command=/opt/bin

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

    $ supervisorctl restart bin


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

    再一次性
    $ supervisorctl reload
    codehz
        7
    codehz  
       Mar 5, 2022 via Android
    虽然 linux 不允许覆盖正在运行的程序,但是你可以先删除了再上传同名文件(
    crackhopper
        8
    crackhopper  
       Mar 5, 2022
    显然用 k8s 更容易搞定。搞很多脚本,脚本维护也是问题。后续系统继续扩展也是问题。
    ClericPy
        9
    ClericPy  
       Mar 5, 2022
    以为挺常见的场景, 结果楼上给的都不是我常见的...

    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
        10
    EminemW  
       Mar 5, 2022
    jenkins 写脚本
    hongzx
        11
    hongzx  
       Mar 5, 2022 via iPhone
    用 docker 来运行
    Git+Drone 自动化部署
    vvhhaaattt
        12
    vvhhaaattt  
       Mar 5, 2022 via Android
    ansible 没人提么?我们之前 supervisor 管理 python 跟 golang ,都用 supervisor 发布。
    vvhhaaattt
        13
    vvhhaaattt  
       Mar 5, 2022 via Android
    @vvhhaaattt ansible 发布……
    ragnaroks
        14
    ragnaroks  
       Mar 5, 2022
    docker
    cosmtrek
        15
    cosmtrek  
       Mar 5, 2022
    k8s +1
    kirile
        16
    kirile  
       Mar 5, 2022
    我是自己用 go 写了个程序, 负责服务停止, 替换, 服务启动, 监听一个 rpc 服务用来接收需要替换的文件压缩包, 把多个服务的路径什么的维护起来. 然后配合 WinForm 客户端, 更新服务的时候就基本上两步就行, 选择服务->点击部署. 另外 WinSCP 可以支持即使 systemd 服务运行着也照样替换 golang 可执行文件, 这个的话也挺方便, 找到目录->拖拽覆盖->重启服务
    xuanbg
        17
    xuanbg  
       Mar 6, 2022
    Jenkins 装一个,每个 service 配一个 job 。哪个有更新点一下哪个 job 的构建就完事。
    Dogtler
        18
    Dogtler  
       Mar 6, 2022 via iPhone
    K8s 滚动更新
    shoaly
        19
    shoaly  
       Mar 6, 2022
    如果是我来做这个方案的话:
    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
        20
    sampeng  
       Mar 6, 2022
    = =!这不就是 docker-composer 干的事么。。。
    sampeng
        21
    sampeng  
       Mar 6, 2022
    公司有一些这种很简单,没必要 k8s 的。。。
    平常升级就是 docker-compose up --force-recreate ,简单可依赖
    initd
        22
    initd  
       Mar 6, 2022
    运行环境是 虚拟机
    brew 自定义 tap
    egoist/bget 下载 github rel

    转换成 容器
    可以用 dokku 的 Paas 持续部署


    运行环境是 容器
    docker-compose
    https://docs.docker.com/compose/
    短链 dc.moz.one

    k8s
    https://kubernetes.io/docs/reference/kubectl/docker-cli-to-kubectl
    短链: dtk.moz.one
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2324 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 62ms · UTC 05:23 · PVG 13:23 · LAX 22:23 · JFK 01:23
    ♥ Do have faith in what you're doing.