原始碼閱讀 goreman

2021-10-07 01:51:52 字數 4650 閱讀 4692

今天我們來一起來學習一下golang乙個第三方程序管理工具goreman

其功能和supervisor類似,用於管理多個程序

一、命令列引數

檢視所有引數,最直接方法是

goreman help
常用命令

goreman start             //啟動所有程序goreman run start command //啟動乙個程序goreman run stop command  //停止乙個程序goreman run list          //檢視goreman執行哪些程序goreman run status        //檢視程序狀態,帶*的是執行中goreman run restart/restart-all/stop/stop-all
goreman啟動時依賴的配置檔案是procfile,來看看這個檔案長什麼樣

web1: ./server -addr :9000web2: ./server -addr :9001
web1是為程序起的名字,其後是該程序啟動命令

編寫乙個簡單的示例server

package mainimport ("fmt""net/http""flag")var (addr string)func indexhandler(w http.responsewriter, r *http.request)func main()func init()
程式接受乙個引數:位址,作為httpserver的啟動位址,提供服務,輸出hello world

啟動goreman

$ goreman start15:07:20 web1 | starting web1 on port 500015:07:20 web2 | starting web2 on port 510015:07:20 web1 | :900015:07:20 web2 | :9001
問題:

程序啟動時,starting web1 on port 5000是什麼意思?

命令列引數中有乙個可選引數port是什麼port?

內部是如何啟動各個程序的?

stop某個程序時是如何操作的?

goreman run status命令是怎麼檢測各個程序狀態的?

帶著這些問題,讀原始碼一**竟

二、整體邏輯梳理

goreman**結構比較簡單

主要邏輯:goreman.go

程序相關:proc.go

rpc定義:rpc.go

2.1 關鍵結構

type config struct// -- process information structure.type procinfo struct
2.2 主要邏輯

main()readconfig() // 讀取並初始化配置(procfile、port、baseport等)start()readprocfile() // 解析procfile檔案,把程序名和啟動命令分別解析為k,vgo startserver() // 在port埠啟動乙個rpc server,接收rpc請求,預設埠號8555startprocs()    // 遍歷所有procs命令,在routine裡啟動乙個個程序//接受終止ctrl+c命令或者stop命令退出
2.3 rpc命令處理

以stop命令為例:當執行goremon run stop web1命令時,實際呼叫的是goremon的對應的rpc stop方法,找到proc.cmd.process的pid對應的程序,給程序傳送終止訊號os.interrupt,從而結束程序

func run(cmd string, args string, serverport uint) errordefer client.close()var ret stringswitch cmdreturn errors.new("unknown command")}// stop do stopfunc (r *goreman) stop(args string, ret *string) (err error)}()errchan := make(chan error, 1)r.rpcchan <- &rpcmessageerr = <-errchanreturn}// 主程序從channel裡讀取rpcmsg處理,目前看只支援stop命令// 其他命令實現是直接呼叫方法來處理,比如start web1,直接呼叫startproc方法select}close(rpcmsg.errch)default:panic("unimplemented rpc message type " + rpcmsg.msg)}...}func terminateproc(proc *procinfo, signal os.signal) errorpgid, err := unix.getpgid(p.pid)if err != nilpid := p.pidif pgid == p.pidtarget, err := os.findprocess(pid)if err != nil// 給process傳送signalreturn target.signal(signal)}
2.4 再看看start命令是怎麼實現的

// 直接呼叫startproc方法,建立程序,這個方法也是goremon程式啟動時呼叫的方法func (r *goreman) start(args string, ret *string) (err error)}()for _, arg := range args}return err}
三、問題解答

程序啟動時,starting web1 on port 5000是什麼意思?

每個程序的port env環境變數(暫時沒發現有什麼用)

命令列引數中有乙個可選引數port是什麼port?

rpc服務監聽的埠號。

內部是如何啟動各個程序的?

見2.2部分。

stop某個程序時是如何操作的?

見2.3部分。

goreman run status命令是怎麼檢測各個程序狀態的?

通過判斷procs裡儲存的cmd是否為nil來判斷程序狀態,如果proc.cmd不為nil,就加個*標識執行中;如果程序被stop了,那麼cmd為nil

func (r *goreman) status(args string, ret *string) (err error)}()*ret = ""for _, proc := range procs  else}return err}
$ goreman run status*web1*web2$ goreman run stop web1$ goreman run statusweb1*web2
總結:

相較於linux的supervisor工具,goremon更簡單易用,管理程序

《原始碼閱讀》原始碼閱讀技巧,原始碼閱讀工具

檢視某個類的完整繼承關係 選中類的名稱,然後按f4 quick type hierarchy quick type hierarchy可以顯示出類的繼承結構,包括它的父類和子類 supertype hierarchy supertype hierarchy可以顯示出類的繼承和實現結構,包括它的父類和...

原始碼閱讀 Glide原始碼閱讀之with方法(一)

前言 本篇基於4.8.0版本 原始碼閱讀 glide原始碼閱讀之with方法 一 原始碼閱讀 glide原始碼閱讀之load方法 二 原始碼閱讀 glide原始碼閱讀之into方法 三 大多數情況下,我們使用glide 就一句 但是這一句 裡面蘊含著成噸的 with方法有以下幾個過載方法 publi...

原始碼閱讀 Glide原始碼閱讀之load方法(二)

原始碼閱讀 glide原始碼閱讀之load方法 二 原始碼閱讀 glide原始碼閱讀之into方法 三 首先,load方法有以下幾個過載方法 public requestbuilder load nullable bitmap bitmap public requestbuilder load nu...