美文网首页
如何让golang编译的iris框架网站程序类似nginx那样可

如何让golang编译的iris框架网站程序类似nginx那样可

作者: Fesion | 来源:发表于2020-07-28 12:05 被阅读0次

    用golang开发的项目越来越多了,他们都跑在服务器上。但是他们都是在shell中运行的,如果关闭了终端,它就自动停止了。这显然不符合我们的需求,服务中断了还怎么服务用户啊。现在市面上流行的有几种解决方案,最简单的是使用nohup /data/wwwroot/build_app& 来实现将进程抛到后台去。也可以使用pm2来启动管理进程的。使用supervise的。也有使用daemon来实现的。下面我们就尝试使用daemon的方式来实现一个守护进程。

    golang的daemon守护进程的代码实现

    golang中启用daemon的方法很简单,已经有别人造好的轮子了,我们就不再造一遍,直接引用即可。使用的是syscall来处理进程。网上的实例使用的是http.Server服务,由于我使用的是iris框架,所以我重新实现了一个针对iris框架可用的daemon守护进程实现方式。它支持启动、关闭、重启等命令,模仿这nginx的命令操作来实现的。

    核心代码

    package main
    
    import (
        "fmt"
        "log"
        "net/http"
        "os"
        "syscall"
        "video"
    
        "github.com/medivh-jay/daemon"
        "github.com/spf13/cobra"
    )
    
    // HTTPServer http 服务器示例
    type HTTPServer struct {
        http *video.Bootstrap
        cmd  *cobra.Command
    }
    
    // PidSavePath pid保存路径
    func (httpServer *HTTPServer) PidSavePath() string {
        return "./"
    }
    
    // Name pid文件名
    func (httpServer *HTTPServer) Name() string {
        return "http"
    }
    
    // SetCommand 从 daemon 获得 cobra.Command 对象
    func (httpServer *HTTPServer) SetCommand(cmd *cobra.Command) {
        // 在这里添加参数时他的参数不是对应服务的 start stop restart 命令的, 比如这个示例服务
        // 他对应的是示例服务命令, s所以这里添加的自定义 flag 应该在 start 之前传入
        cmd.PersistentFlags().StringP("test", "t", "yes", "")
        httpServer.cmd = cmd
    }
    
    // Start 启动web服务
    func (httpServer *HTTPServer) Start() {
        fmt.Println(httpServer.cmd.Flags().GetString("test"))
        http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
            fmt.Println("hello world")
            _, _ = writer.Write([]byte("hello world"))
        })
        httpServer.http = video.New(8088, "debug")
        httpServer.http.Serve()
    }
    
    // Stop 关闭web服务
    func (httpServer *HTTPServer) Stop() error {
        fmt.Println("准备关闭服务器")
        err := httpServer.http.Shutdown()
        fmt.Println("服务器已经关闭")
        return err
    }
    
    // Restart 重启web服务前关闭http服务
    func (httpServer *HTTPServer) Restart() error {
        fmt.Println("服务器关闭中")
        err := httpServer.Stop()
        return err
    }
    
    func main() {
        // 自定义输出文件
        out, _ := os.OpenFile("./http.log", os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
        err, _ := os.OpenFile("./http_err.log", os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
    
        // 初始化一个新的运行程序
        proc := daemon.NewProcess(new(HTTPServer)).SetPipeline(nil, out, err)
        proc.On(syscall.SIGTERM, func() {
            fmt.Println("a custom signal")
        })
        // 示例,多级命令服务
        // 不要共享一个 worker 对象指针
        daemon.GetCommand().AddWorker(proc).AddWorker(proc)
        // 示例,主服务
        daemon.Register(proc)
    
        // 运行
        if rs := daemon.Run(); rs != nil {
            log.Fatalln(rs)
        }
    }
    

    bootstrap里面是iris的逻辑

    package video
    
    import (
        "fmt"
        "github.com/kataras/iris/v12"
        "github.com/kataras/iris/v12/middleware/recover"
    )
    
    type Bootstrap struct {
        Application *iris.Application
        Port        int
        LoggerLevel string
    }
    
    func New(port int, loggerLevel string) *Bootstrap {
        var bootstrap Bootstrap
        bootstrap.Application = iris.New()
        bootstrap.Port = port
        bootstrap.LoggerLevel = loggerLevel
    
        return &bootstrap
    }
    
    func (bootstrap *Bootstrap) loadGlobalMiddleware() {
        bootstrap.Application.Use(recover.New())
    }
    
    func (bootstrap *Bootstrap) LoadRoutes() {
        Register(bootstrap.Application)
    }
    
    func (bootstrap *Bootstrap) Serve() {
        bootstrap.Application.Logger().SetLevel(bootstrap.LoggerLevel)
        bootstrap.loadGlobalMiddleware()
        bootstrap.LoadRoutes()
    
        bootstrap.Application.Run(
            iris.Addr(fmt.Sprintf(":%d", bootstrap.Port)),
            iris.WithoutServerError(iris.ErrServerClosed),
            iris.WithoutBodyConsumptionOnUnmarshal,
        )
    }
    
    func (bootstrap *Bootstrap) Shutdown() error {
        bootstrap.Shutdown()
    
        return nil
    }
    
    

    控制器代码

    package video
    
    import (
        "github.com/kataras/iris/v12"
        "os"
        "time"
    )
    
    func Index(ctx iris.Context) {
      ctx.WriteString("hello")
    }
    
    func ParseVideo(ctx iris.Context) {
        v, err := os.Open("vv.mp4")
        if err != nil {
            ctx.WriteString(err.Error())
            return
        }
        defer v.Close()
        ctx.ServeContent(v, "vv.mp4", time.Now(), true)
    }
    
    

    路由器代码

    package video
    
    import "github.com/kataras/iris/v12"
    
    func Register(app *iris.Application) {
        app.Use(Cors)
        app.Use(ParseToken)
    
      app.Get("/", Index)
        app.Get("/play", ParseVideo)
    }
    
    

    中间件代码,用来处理cors

    package video
    
    import (
        "github.com/kataras/iris/v12"
    )
    
    func Cors(ctx iris.Context) {
        origin := ctx.GetHeader("Origin")
        if origin == "" {
            origin = ctx.GetHeader("Referer")
        }
        ctx.Header("Access-Control-Allow-Origin", origin)
        ctx.Header("Access-Control-Allow-Credentials", "true")
        ctx.Header("Access-Control-Expose-Headers", "Content-Disposition")
        if ctx.Request().Method == "OPTIONS" {
            ctx.Header("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,PATCH,OPTIONS")
            ctx.Header("Access-Control-Allow-Headers", "Content-Type, Api, Accept, Authorization, Admin")
            ctx.StatusCode(204)
            return
        }
        ctx.Next()
    }
    
    func ParseToken(ctx iris.Context) {
    
        ctx.Next()
    }
    

    相关文章

      网友评论

          本文标题:如何让golang编译的iris框架网站程序类似nginx那样可

          本文链接:https://www.haomeiwen.com/subject/jikfrktx.html