systemctl status monitor
package main import ( "fmt" "io/ioutil" "net/http" "os" "sync" "time" "monitor/utils/slack" "gopkg.in/yaml.v2" ) var config struct { Frequency int Urls []string } type statusType struct { values map[string]int mux sync.Mutex } var status = statusType{values: make(map[string]int)} func (s *statusType) set(url string, value int) { s.mux.Lock() s.values[url] = value s.mux.Unlock() } func init() { data, err := ioutil.ReadFile("config.yaml") if err != nil { fmt.Printf("Invalid config: %s\n", err) os.Exit(0) } err = yaml.Unmarshal(data, &config) if err != nil { fmt.Printf("Invalid config: %s\n", err) os.Exit(0) } for _, url := range config.Urls { status.set(url, 200) } } func main() { ticker := time.NewTicker(time.Duration(config.Frequency) * time.Second) for _ = range ticker.C { for _, url := range config.Urls { go check(url) } } } func check(url string) { res, err := http.Get(url) if err != nil { res = &http.Response{StatusCode: 500} } // the memory problem occurs when this condition is never satisfied, so I didn't post the slack package. if res.StatusCode != status.values[url] { status.set(url, res.StatusCode) err := slack.Alert(url, res.StatusCode) if err != nil { fmt.Println(err) } } }
如果这属于Code Review,那么我会把它放在那里.
1> Adrian..:
是的,这是内存泄漏.我可以发现一个明显的来源是你没有从你的请求中关闭响应主体:
func check(url string) { res, err := http.Get(url) if err != nil { res = &http.Response{StatusCode: 500} } else { defer res.Body.Close() // You need to close the response body! } if res.StatusCode != status.values[url] { status.set(url, res.StatusCode) err := slack.Alert(url, res.StatusCode) if err != nil { fmt.Println(err) } } }
更好的是,所以Go可以使用keepalive,你想要阅读全身并关闭它:
defer func() { io.Copy(ioutil.Discard, res.Body) res.Body.Close() }()
pprof