美文网首页
如何让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那样可

    用golang开发的项目越来越多了,他们都跑在服务器上。但是他们都是在shell中运行的,如果关闭了终端,它就自动...

  • iris-开始

    iris是golang的web框架,官方地址:https://github.com/kataras/iris/,支...

  • 基于scratch的iris容器示例

    本示例基于golang iris的Hello World,静态编译,基于空白镜像scratch,解决了时区问题 创...

  • 使用 Iris 打造一款个人博客(配置篇)

    Golang:使用 Iris 打造一款个人博客(一) Iris 号称世界第一快的框架 实际上测试对比几款高性能的 ...

  • iris 框架依赖注入使用

    iris 框架依赖注入使用 介绍 golang开发web应用一般会选个web框架开始开发,web框架提供了丰富的功...

  • golang进行交叉编译

    golang进行交叉编译 交叉编译即编译不同操作系统平台的可执行程序 golang执行交叉编译,只需要使用两个变量...

  • 面试总结

    笔试题 1.如何对Golang程序做性能分析和调优?如何排查Golang程序的内存泄漏? 1)使用golang的工...

  • go如何进行交叉编译

    golang交叉编译 问题 golang如何在一个平台编译另外一个平台可以执行的文件。比如在mac上编译Windo...

  • macOS本地搭建leanote

    下载以下软件 Golang(编译环境) Revel (WEB框架) mongodb(数据库) leanote(蚂蚁...

  • MacOS中使用VSCode调试Nginx

    一. 编译运行Nginx 详细过程可参考博文:Nginx源码编译安装教程 配置调试功能 一定要开启Nginx调试功...

网友评论

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

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