目录

1. 前言

之前提到过目前我们的进程都是通过supervisor(http://supervisord.org/)这样一个进程管理软件进行管理的,也专门做过专题翻译过supervisor的一些内容:

我们会发现3.0以上的版本会有xml-rpc接口(http://supervisord.org/xmlrpc.html)可以通过对应接口控制supervisor管理的进程,包括获取对应的日志、运行状态等功能,这在实际开发过程中获取这些信息在web上进行控制、查询也是非常有帮助的,所以这里对go如何进行supervisor管理进程的信息的处理做简单的总结。

2. 管理web

一般在配置文件中添加:

[inet_http_server]
port=9001

即可通过9001端口访问一个web页面:

而通过xml-rpc可以获取状态,对这些进程进行控制管理,查看对应日志等。

注意:处于安全可能会需要配置该web的用户名和密码,但是为了方便进行程序管理,最好不要配置鉴权,否则程序可能由于鉴权失败无法进行控制。

3. go处理库

这里给个go-supervisor的处理库:

import "github.com/abrander/go-supervisord"
  
func main() {
	c, err := supervisord.newclient("http://127.0.0.1:9001/rpc2")
	if err != nil {
		panic(err.error())
	}
	
	err = c.clearlog()
	if err != nil {
		panic(err.error())
	}
	
	err = c.restart()
	if err != nil {
		panic(err.error())
	}
}

对应库中获取stdout的实时日志接口没有实现,我们可以通过websocket的方式来实现该接口自行扩展,主要是通过进程信息获取对应日志文件名。

4. 实时日志处理代码片段

这里给个通过supervisor获取日志文件名,然后通过websocket读取日志进行实时日志上报的代码片段:

func (s *businesslogservice) taillog(name string, ws *ghttp.websocket) error {
	c, err := supervisord.newclient("http://127.0.0.1:9001/rpc2")
	if err != nil {
		return err
	}
	defer c.close()
	processinfo, err := c.getprocessinfo(name)
	if err != nil {
		logger.error(err)
		return err
	}
	filename = processinfo.stdoutlogfile
	logger.debug(filename)
	s.servews(ws)
	return nil
}

/***
编译时需要安装以下依赖:
go get github.com/gorilla/websocket
go get github.com/hpcloud/tail
*/
const (
	// time allowed to write the file to the client.
	//writewait = 1 * time.second
	writewait = 100 * time.millisecond

	// time allowed to read the next pong message from the client.
	//pongwait = 24 * time.hour
	pongwait = 60 * time.second

	// send pings to client with this period. must be less than pongwait.
	pingperiod = (pongwait * 9) / 10

	// poll file for changes with this period.
	fileperiod = 1 * time.second
)

var (
	filename string
)

func (s *businesslogservice) readfileifmodified(lastmod time.time) ([]byte, time.time, error) {
	fi, err := os.stat(filename)
	if err != nil {
		return nil, lastmod, err
	}
	if !fi.modtime().after(lastmod) {
		return nil, lastmod, nil
	}
	p, err := ioutil.readfile(filename)
	if err != nil {
		return nil, fi.modtime(), err
	}
	return p, fi.modtime(), nil
}

func (s *businesslogservice) reader(ws *ghttp.websocket) {
	defer ws.close()
	ws.setreadlimit(512)
	ws.setreaddeadline(time.now().add(pongwait))
	ws.setponghandler(func(string) error { ws.setreaddeadline(time.now().add(pongwait)); return nil })
	for {
		_, _, err := ws.readmessage()
		if err != nil {
			logger.warn(err)
			break
		}
	}
}

func (s *businesslogservice) tailfile() *tail.tail {
	tailfd, err := tail.tailfile(filename, tail.config{
		reopen:    true,                                 // 文件被移除或被打包,需要重新打开
		follow:    true,                                 // 实时跟踪
		location:  &tail.seekinfo{offset: 0, whence: 2}, // 如果程序出现异常,保存上次读取的位置,避免重新读取。
		mustexist: false,                                // 如果文件不存在,是否推出程序,false是不退出
		poll:      true,
	})

	if err != nil {
		logger.error("tail file failed, err:", err)
		return nil
	}
	return tailfd
}

func (s *businesslogservice) writer(ws *ghttp.websocket) {
	tailfd := s.tailfile()
	pingticker := time.newticker(pingperiod)
	fileticker := time.newticker(fileperiod)
	maxtimeout := time.newticker(time.duration(1) * time.minute)
	defer func() {
		pingticker.stop()
		fileticker.stop()
		ws.close()
	}()

	for {
		select {
		case msg, ok := <-tailfd.lines:
			if ok {
				ws.setwritedeadline(time.now().add(writewait))
				logger.debug("read file content: %s\n", msg)
				if err := ws.writemessage(websocket.textmessage, []byte(msg.text)); err != nil {
					return
				}
			}
		case <-pingticker.c:
			ws.setwritedeadline(time.now().add(writewait))
			if err := ws.writemessage(websocket.pingmessage, []byte{}); err != nil {
				return
			}
		case <-maxtimeout.c:
			ws.writemessage(websocket.textmessage, []byte("maximum timeout"))
			ws.close()
		}
	}
}

func (s *businesslogservice) servews(ws *ghttp.websocket) {
	go s.writer(ws)
	s.reader(ws)
}

到此这篇关于go操作supervisor xml rpc接口及注意事项的文章就介绍到这了,更多相关go操作supervisor xml rpc接口内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!