• RTSP协议视频流媒体安防智能分析平台EasyNVR如何启动多个nignx?


    Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,因此TSINGSEE青犀视频云边端架构视频智能分析平台在运行时也会使用nginx服务器。

    部分情况下,EasyNVR启动时只带起来了一个nginx,但是一个nginx的能力不能满足EasyNVR直播转码分发以及存储的需求,因此这时我们需要启动多个nginx。本文就讲一下启动多个Nginx的方法。

    在EasyNVR程序启动的时候,会默认启动一个nginx,我们可以查看这部分代码,仿照这部分代码编写启动多个nginx的代码。

    func Start() (err error) {
      exe := EXE()
      MutliStrart(exe, 0)
      enable := utils.Conf().Section("base_config").Key("multi_nginx_enable").MustBool(false)
      if enable {
         number := utils.Conf().Section("base_config").Key("multi_nginx_number").MustInt()
         for i := 1; i < number; i++ {
            MutliStrart(MultiEXE(i), i)
         }
      }
      return
    }
    
    

    在启动的时候,默认会先启动EasyNVR里面默认的nginx,然后根据配置文件启动多个nginx,参考代码如下:

    func MutliStrart(exe string, index int) (err error) {
       if exe == "" {
          err = fmt.Errorf("dss bin path not found")
          return
       }
       pids, _ := filepath.Glob(filepath.Join(filepath.Dir(exe), "logs/*.pid"))
       if pids != nil && index == 0 {
          utils.Logf("%s find pid file", filepath.Base(exe))
          if err := Stop(); err == nil {
             //wait for stop done
             for i := 0; i < 10; i++ {
                time.Sleep(1 * time.Second)
                pids, _ := filepath.Glob(filepath.Join(filepath.Dir(exe), "logs/*.pid"))
                if pids == nil {
                   log.Printf("%s wait for stop done", filepath.Base(exe))
                   break
                }
             }
          }
       }
       //var httpPort int
       //var rtmpPort int
       //if index != 0 {
       // httpPort = int(GetHTTPPort()) + index
       // rtmpPort = int(GetRTMPPort()) + index
       // SetMutliHTTPPort(uint(httpPort), index)
       // SetMutliRTMPPort(uint(rtmpPort), index)
       //}
       if utils.IsPortInUse(int(GetHTTPPort())) && index == 0 {
          err = fmt.Errorf("port[%d] In Use", GetHTTPPort())
          return
       }
       if utils.IsPortInUse(int(GetRTMPPort())) && index == 0 {
          err = fmt.Errorf("port[%d] In Use", GetRTMPPort())
          return
       }
       err = utils.EnsureDir(HLSDir())
       if err != nil {
          log.Println(err)
          return
       }
       err = utils.EnsureDir(RecordDir())
       if err != nil {
          log.Println(err)
          return
       }
       err = utils.EnsureDir(filepath.Join(filepath.Dir(exe), "logs"))
       if err != nil {
          log.Println(err)
          return
       }
       err = utils.EnsureDir(filepath.Join(filepath.Dir(exe), "temp"))
       if err != nil {
          log.Println(err)
          return
       }
       cmd := exec.Command(exe)
       cmd.Dir = filepath.Dir(exe)
       cmd.SysProcAttr = &syscall.SysProcAttr{
          HideWindow:    true,
          CreationFlags: syscall.CREATE_NEW_PROCESS_GROUP,
       }
       err = cmd.Start()
       if err != nil {
          log.Printf("start dss error, %v", err)
          return
       }
       go func() {
          if err := cmd.Wait(); err != nil {
             log.Printf("wait dss error, %v", err)
          }
       }()
       if index == 0 {
          go StartTicker()
       } else {
          go StratMutliTicker(index)
       }
       if index == 0 {
          log.Println("%s start ok, rtmp port[%d], http port[%d]", filepath.Base(exe), GetRTMPPort(), GetHTTPPort())
       } else {
          log.Println("%s start ok, rtmp port[%d], http port[%d]", filepath.Base(exe), GetMutliRTMPPort(index), GetMutliHTTPPort(index))
       }
       return
    }
    
    

    至此,启动多个nginx代码就可以了。但是,现在EasyNVR每个通道还是向默认的nginx进行推流录像,推流直播,因此我们需要在相应的地方进行修改。

    func (channel *ChannelInfo) InitPushers(camera *models.Camera) {
       channel.lock.Lock()
       defer channel.lock.Unlock()
    
       if channel.client == nil {
          return
       }
       rtmpHost := utils.Conf().Section("base_config").Key("rtmp_host").MustString("")
       // 根据配置文件
       enable := utils.Conf().Section("base_config").Key("hls_record_enable").MustBool(true)
       var application = ""
       if enable {
          application = "hls"
       } else {
          application = "record"
       }
       if rtmpHost == "" {
          var rtmpPort uint
          enable := utils.Conf().Section("base_config").Key("multi_nginx_enable").MustBool(false)
          if enable {
             number := utils.Conf().Section("base_config").Key("multi_nginx_number").MustInt()
             channelId := int(channel.Channel)
             index := channelId % number
             rtmpPort = dss.GetMutliRTMPPort(index)
          } else {
             rtmpPort = dss.GetRTMPPort()
          }
          channel.localPusher = stream.NewStreamPusher(fmt.Sprintf("%s - 推流直播", camera.Name), fmt.Sprintf("rtmp://127.0.0.1:%d/%s/%s", rtmpPort, application, StreamID(camera.ID)))
          channel.localPusher.AudioEnable = camera.Reserve1 == "1"
          channel.recordPusher = stream.NewStreamPusher(fmt.Sprintf("%s - 推流录像", camera.Name), fmt.Sprintf("rtmp://127.0.0.1:%d/record/%s", rtmpPort, StreamID(camera.ID)))
          channel.recordPusher.AudioEnable = camera.Reserve1 == "1"
       } else {
          channel.localPusher = stream.NewStreamPusher(fmt.Sprintf("%s - 推流直播", camera.Name), fmt.Sprintf("rtmp://%s/%s/%s", rtmpHost, application, StreamID(camera.ID)))
          channel.localPusher.AudioEnable = camera.Reserve1 == "1"
          channel.recordPusher = stream.NewStreamPusher(fmt.Sprintf("%s - 推流录像", camera.Name), fmt.Sprintf("rtmp://%s/record/%s", rtmpHost, StreamID(camera.ID)))
          channel.recordPusher.AudioEnable = camera.Reserve1 == "1"
       }
    
    

    经过这样修改后,例如:
    EasyNVR配置启动3个nginx,通道1就向nginx1推流,通道2就向nginx2推流,通道3就向nginx3推流,通道4就向nginx1推流…每隔3个通道一次轮回。至此,EasyNVR多nginx方案就已经实现了。

    EasyNVR视频平台被运用在很多场景下,包括智慧水利、智慧交通、校园安防等,当然还有更多的场景在拓展当中,如果大家有需求,欢迎联系我们,TSINGSEE青犀视频团队将根据大家的需求出具最合适的解决方案。

  • 相关阅读:
    [原创] 基础中的基础(三):理解数据库的几种键和几个范式
    [原创] 思维导图笔记(一):设计模式
    [原创] 基础中的基础(二):C/C++ 中 const 修饰符用法总结
    [原创] 基础中的基础(一):简单排序算法总结(附代码)
    [转载] Linux 下产生和调试core文件
    [转载] C++异常处理机制
    spring cloud开发、部署注意
    使用Spring Sleuth和Zipkin跟踪微服务
    HttpClient4.5 SSL访问工具类
    多线程处理中Future的妙用
  • 原文地址:https://www.cnblogs.com/EasyNVR/p/14043723.html
Copyright © 2020-2023  润新知