今天我們來一起來學習一下golang乙個第三方程序管理工具goreman
其功能和supervisor類似,用於管理多個程序
一、命令列引數
檢視所有引數,最直接方法是
goreman help
常用命令
goreman啟動時依賴的配置檔案是procfile,來看看這個檔案長什麼樣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
web1是為程序起的名字,其後是該程序啟動命令web1: ./server -addr :9000
web2: ./server -addr :9001
編寫乙個簡單的示例server
程式接受乙個引數:位址,作為httpserver的啟動位址,提供服務,輸出hello worldpackage main
import (
"fmt"
"net/http"
"flag"
)
var (
addr string
)
func indexhandler(w http.responsewriter, r *http.request)
func main()
func init()
啟動goreman
問題:$ goreman start
15:07:20 web1 | starting web1 on port 5000
15:07:20 web2 | starting web2 on port 5100
15:07:20 web1 | :9000
15: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 關鍵結構
2.2 主要邏輯type config struct
// -- process information structure.
type procinfo struct
2.3 rpc命令處理main()
readconfig() // 讀取並初始化配置(procfile、port、baseport等)
start()
readprocfile() // 解析procfile檔案,把程序名和啟動命令分別解析為k,v
go startserver() // 在port埠啟動乙個rpc server,接收rpc請求,預設埠號8555
startprocs() // 遍歷所有procs命令,在routine裡啟動乙個個程序
//接受終止ctrl+c命令或者stop命令退出
以stop命令為例:當執行goremon run stop web1命令時,實際呼叫的是goremon的對應的rpc stop方法,找到proc.cmd.process的pid對應的程序,給程序傳送終止訊號os.interrupt,從而結束程序
2.4 再看看start命令是怎麼實現的func run(cmd string, args string, serverport uint) error
defer client.close()
var ret string
switch cmd
return errors.new("unknown command")
}
// stop do stop
func (r *goreman) stop(args string, ret *string) (err error)
}()
errchan := make(chan error, 1)
r.rpcchan <- &rpcmessage
err = <-errchan
return
}
// 主程序從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) error
pgid, err := unix.getpgid(p.pid)
if err != nil
pid := p.pid
if pgid == p.pid
target, err := os.findprocess(pid)
if err != nil
// 給process傳送signal
return target.signal(signal)
}
三、問題解答// 直接呼叫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 status
web1
*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...