Golang应用如何保持长期运行

Golang应用如何保持长期运行 我们有一个使用 Gin 框架编写的 Golang REST Web API。在 Windows 服务器上,它在命令窗口中运行。如果有人关闭命令窗口,应用程序就会关闭。

如何解决这个问题?我们能否将其设置为像 Windows 服务一样运行。

2 回复

你检查过这个示例吗?

更多关于Golang应用如何保持长期运行的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


要让Golang应用在Windows上作为服务长期运行,可以使用以下方法:

方法一:使用sc命令创建Windows服务

# 1. 构建可执行文件
go build -o myapp.exe main.go

# 2. 创建Windows服务
sc create MyGoService binPath= "C:\path\to\myapp.exe" start= auto

# 3. 启动服务
sc start MyGoService

# 4. 查看服务状态
sc query MyGoService

# 5. 停止服务
sc stop MyGoService

# 6. 删除服务
sc delete MyGoService

方法二:使用NSSM(Non-Sucking Service Manager)

NSSM是更友好的Windows服务管理工具:

  1. 下载NSSM:https://nssm.cc/download
  2. 安装服务:
# 将nssm.exe放在系统PATH或应用目录
nssm install MyGoService
# 在弹出的GUI中选择你的Go可执行文件
  1. 命令行安装:
nssm install MyGoService "C:\path\to\myapp.exe"
nssm set MyGoService AppDirectory "C:\path\to\"
nssm start MyGoService

方法三:使用Go的winsvc包(编程方式)

package main

import (
    "context"
    "fmt"
    "log"
    "net/http"
    "os"
    "time"
    
    "github.com/gin-gonic/gin"
    "golang.org/x/sys/windows/svc"
    "golang.org/x/sys/windows/svc/debug"
    "golang.org/x/sys/windows/svc/eventlog"
)

var elog debug.Log

type myservice struct{}

func (m *myservice) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (ssec bool, errno uint32) {
    changes <- svc.Status{State: svc.StartPending}
    
    // 启动Gin服务器
    go startGinServer()
    
    changes <- svc.Status{State: svc.Running, Accepts: svc.AcceptStop | svc.AcceptShutdown}
    
    for {
        select {
        case c := <-r:
            switch c.Cmd {
            case svc.Interrogate:
                changes <- c.CurrentStatus
            case svc.Stop, svc.Shutdown:
                changes <- svc.Status{State: svc.StopPending}
                // 执行清理操作
                return false, 0
            }
        }
    }
}

func startGinServer() {
    router := gin.Default()
    
    router.GET("/health", func(c *gin.Context) {
        c.JSON(http.StatusOK, gin.H{"status": "healthy"})
    })
    
    router.GET("/api/data", func(c *gin.Context) {
        c.JSON(http.StatusOK, gin.H{"message": "Hello from Windows Service"})
    })
    
    if err := router.Run(":8080"); err != nil {
        elog.Error(1, fmt.Sprintf("Failed to start server: %v", err))
    }
}

func main() {
    // 判断是否在服务上下文中运行
    isIntSess, err := svc.IsAnInteractiveSession()
    if err != nil {
        log.Fatalf("failed to determine if we are running in an interactive session: %v", err)
    }
    
    if !isIntSess {
        elog, err = eventlog.Open("MyGoService")
        if err != nil {
            log.Fatalf("failed to open event log: %v", err)
        }
        defer elog.Close()
        
        elog.Info(1, "Starting MyGoService")
        err = svc.Run("MyGoService", &myservice{})
        if err != nil {
            elog.Error(1, fmt.Sprintf("Service failed: %v", err))
            return
        }
        elog.Info(1, "MyGoService stopped")
    } else {
        // 交互式运行(调试用)
        startGinServer()
    }
}

方法四:使用WinSW(Windows Service Wrapper)

创建 myapp.xml 配置文件:

<service>
    <id>MyGoService</id>
    <name>My Go Application</name>
    <description>Go REST API Service</description>
    <executable>C:\path\to\myapp.exe</executable>
    <logpath>C:\logs\myapp</logpath>
    <log mode="roll-by-size">
        <sizeThreshold>10240</sizeThreshold>
        <keepFiles>8</keepFiles>
    </log>
    <onfailure action="restart" delay="10 sec"/>
</service>

安装服务:

# 下载WinSW:https://github.com/winsw/winsw/releases
winsw.exe install myapp.xml
winsw.exe start myapp.xml

方法五:使用任务计划程序

  1. 打开"任务计划程序"
  2. 创建基本任务
  3. 触发器设置为"计算机启动时"
  4. 操作设置为"启动程序",选择你的Go可执行文件
  5. 勾选"不管用户是否登录都要运行"

这些方法都能确保你的Gin应用在Windows服务器上作为服务长期运行,不会因命令窗口关闭而停止。

回到顶部