Golang在生产环境中如何实现类似Nodejs的pm2永久运行?

Golang在生产环境中如何实现类似Nodejs的pm2永久运行? 我想让我的Go程序像Node.js的pm2一样永远运行。

21 回复

Supervisor

更多关于Golang在生产环境中如何实现类似Nodejs的pm2永久运行?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我使用 Ubuntu 18 和 CentOS 7。

我会检查,谢谢。

好的,我会去查看一下,谢谢大家。

我会去看看的,谢谢。

谢谢,我会去看看。

像这样吗,(pm2 start main.exe)?

好的,我刚刚搞定了,哈哈,谢谢。

我实际上使用 pm2 来保持我的 Go 二进制服务运行,并用于日志记录和监控。

那么我将改变我的问题:如何在不关闭Go程序的情况下退出Linux终端?

func main() {
    fmt.Println("hello world")
}

你在寻找 systemd 和/或 supervisor 吗?只是猜测一下……

[OT] 永远?我认为你在互联网上找到的任何解决方案都无法提供那种级别的保证,要知道,永远是一段非常长的时间。 🙂 [/OT]

我不知道pm2是什么,但这归根结底是要了解目标发行版的初始化系统或Windows服务,并以至少与它们兼容的方式部署你的程序,甚至可能需要提供必要的单元/服务文件。

您利用的是您初始化系统的能力。如今最主流的可能是 systemd,但您的系统具体使用哪一个,我并不知道,因为您没有告知您使用的是哪种 Linux 发行版。

如果我没记错的话,两者都使用 systemd。我对 CentOS 很确定,不过 Ubuntu 在过去 10 年里更换过几次初始化系统,所以你需要单独检查一下。

这与Go语言无关……但是

Linux Handbook Logo Linux Handbook – 22 Apr 19

Learn Linux

在后台和前台运行Linux命令

学习如何在Linux中以后台方式运行命令。你还将学习如何将后台作业带回前台。

在 Linux 上,你可以使用 screen,但当系统关闭时,这些 screen 会话会消失,换句话说程序会停止。另一个选择是使用以下代码创建服务:

[Unit]
Description=Service description
Requires=network.target

[Service]
User=root
Restart=on-failure
ExecStart=/usr/bin/NAMEOFFILE

[Install]
WantedBy=multi-user.target

每次更新代码后,只需用新构建的文件替换此路径下的旧文件: /usr/bin/NAMEOFFILE

并运行以下命令: sudo service NAMEOFSERVICE restart

在Go中实现类似pm2的永久运行,推荐使用systemd或容器化方案。以下是具体实现:

1. 使用systemd(推荐生产环境)

创建service文件 /etc/systemd/system/your-app.service

[Unit]
Description=Your Go Application
After=network.target

[Service]
Type=simple
User=appuser
WorkingDirectory=/opt/your-app
ExecStart=/opt/your-app/your-app
Restart=always
RestartSec=10
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=your-app
Environment="GIN_MODE=release"

# 资源限制
LimitNOFILE=65536
LimitNPROC=4096

[Install]
WantedBy=multi-user.target

启用并启动服务:

sudo systemctl daemon-reload
sudo systemctl enable your-app
sudo systemctl start your-app

2. 使用supervisor

安装supervisor后配置 /etc/supervisor/conf.d/your-app.conf

[program:your-app]
command=/opt/your-app/your-app
directory=/opt/your-app
user=appuser
autostart=true
autorestart=true
startsecs=10
startretries=3
stdout_logfile=/var/log/your-app/stdout.log
stderr_logfile=/var/log/your-app/stderr.log
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=10
environment=GIN_MODE=release

3. 程序内部实现守护进程

package main

import (
    "log"
    "net/http"
    "os"
    "os/exec"
    "time"
)

func main() {
    // 检查是否已经是守护进程
    if os.Getppid() != 1 {
        // 创建子进程
        cmd := exec.Command(os.Args[0], os.Args[1:]...)
        cmd.Stdout = os.Stdout
        cmd.Stderr = os.Stderr
        cmd.Start()
        os.Exit(0)
    }

    // 守护进程逻辑
    runApplication()
}

func runApplication() {
    // 心跳检测和健康检查
    go func() {
        ticker := time.NewTicker(30 * time.Second)
        defer ticker.Stop()
        
        for range ticker.C {
            // 执行健康检查
            if !healthCheck() {
                log.Println("Health check failed, restarting...")
                restartSelf()
            }
        }
    }()

    // 主服务逻辑
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Application is running"))
    })
    
    log.Println("Server starting on :8080")
    if err := http.ListenAndServe(":8080", nil); err != nil {
        log.Fatal("Server failed: ", err)
    }
}

func healthCheck() bool {
    // 实现健康检查逻辑
    return true
}

func restartSelf() {
    cmd := exec.Command(os.Args[0], os.Args[1:]...)
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    cmd.Start()
    os.Exit(0)
}

4. 使用容器化(Docker)

创建Dockerfile:

FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o main .

FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/main .
EXPOSE 8080
CMD ["./main"]

使用docker-compose管理:

version: '3.8'
services:
  app:
    build: .
    restart: always
    ports:
      - "8080:8080"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    deploy:
      resources:
        limits:
          memory: 512M

5. 使用第三方工具

安装并使用 daemonize

# 安装daemonize
sudo apt-get install daemonize

# 运行Go程序
daemonize -c /opt/your-app -u appuser -p /var/run/your-app.pid \
  -l /var/lock/your-app -v -e /var/log/your-app/error.log \
  /opt/your-app/your-app

对于生产环境,systemd是最稳定和标准的选择,提供完整的进程管理、日志收集和资源控制功能。

回到顶部