Prometheus 实战于源码分析之webHandler
上一篇介紹了服務啟動基本流程,但里面有幾個點沒有展開,這里還是要分析一下,首先介紹這個webHandler,它是一個web http請求的服務端。先看初始
func New(o *Options) *Handler {router := route.New(func(r *http.Request) (context.Context, error) {return o.Context, nil})cwd, err := os.Getwd()if err != nil {cwd = "<error retrieving current working directory>"}h := &Handler{router: router,listenErrCh: make(chan error),quitCh: make(chan struct{}),reloadCh: make(chan chan error),options: o,versionInfo: o.Version,birth: time.Now(),cwd: cwd,flagsMap: o.Flags,context: o.Context,targetManager: o.TargetManager,ruleManager: o.RuleManager,queryEngine: o.QueryEngine,storage: o.Storage,notifier: o.Notifier,apiV1: api_v1.NewAPI(o.QueryEngine, o.Storage, o.TargetManager, o.Notifier),now: model.Now,}if o.RoutePrefix != "/" {// If the prefix is missing for the root path, prepend it.router.Get("/", func(w http.ResponseWriter, r *http.Request) {http.Redirect(w, r, o.RoutePrefix, http.StatusFound)})router = router.WithPrefix(o.RoutePrefix)}instrh := prometheus.InstrumentHandlerinstrf := prometheus.InstrumentHandlerFuncrouter.Get("/", func(w http.ResponseWriter, r *http.Request) {router.Redirect(w, r, "/graph", http.StatusFound)})router.Get("/alerts", instrf("alerts", h.alerts))router.Get("/graph", instrf("graph", h.graph))router.Get("/status", instrf("status", h.status))router.Get("/flags", instrf("flags", h.flags))router.Get("/config", instrf("config", h.config))router.Get("/rules", instrf("rules", h.rules))router.Get("/targets", instrf("targets", h.targets))router.Get("/version", instrf("version", h.version))router.Get("/heap", instrf("heap", dumpHeap))router.Get(o.MetricsPath, prometheus.Handler().ServeHTTP)router.Get("/federate", instrh("federate", httputil.CompressionHandler{Handler: http.HandlerFunc(h.federation),}))h.apiV1.Register(router.WithPrefix("/api/v1"))router.Get("/consoles/*filepath", instrf("consoles", h.consoles))router.Get("/static/*filepath", instrf("static", serveStaticAsset))if o.UserAssetsPath != "" {router.Get("/user/*filepath", instrf("user", route.FileServe(o.UserAssetsPath)))}if o.EnableQuit {router.Post("/-/quit", h.quit)}router.Post("/-/reload", h.reload)router.Get("/-/reload", func(w http.ResponseWriter, r *http.Request) {w.WriteHeader(http.StatusMethodNotAllowed)fmt.Fprintf(w, "This endpoint requires a POST request.\n")})router.Get("/debug/*subpath", http.DefaultServeMux.ServeHTTP)router.Post("/debug/*subpath", http.DefaultServeMux.ServeHTTP)return h }這個代碼寫的還是很工整的,先看router,這個里面定義了這個handler所提供的方法,譬如,獲取告警的方法router.Get(“/alerts”, instrf(“alerts”, h.alerts)),還有就是打開首頁router.Redirect(w, r, “/graph”, http.StatusFound)跳轉(zhuǎn)到首頁等,還有一個特別的方法也需要單獨接受一下就是router.Post(“/-/reload”, h.reload),這個牛逼了,就是可以通過發(fā)送post請求就可以重新relaod配置了,這個和上一篇啟動里面說的對應上了,可以通過SIGHUP和reload請求兩種方式重新加載配置。看代碼:
func (h *Handler) reload(w http.ResponseWriter, r *http.Request) {rc := make(chan error)h.reloadCh <- rcif err := <-rc; err != nil {http.Error(w, fmt.Sprintf("failed to reload config: %s", err), http.StatusInternalServerError)} }管道reloadCh chan chan error里是管道的管道。
這個webhandler還提供其他的查詢服務如target
還有最后一個服務需要介紹就是prometheus提供自身監(jiān)控數(shù)據(jù)的接口
mfs, err := DefaultGatherer.Gather()通過Gather()方法收集
wg.Add(len(r.collectorsByID))go func() {wg.Wait()close(metricChan)}()for _, collector := range r.collectorsByID {go func(collector Collector) {defer wg.Done()collector.Collect(metricChan)}(collector)}可以通過http://x.x.x.x:9090/metrics訪問監(jiān)控數(shù)據(jù)
剩下的就是服務的啟動,這個就是一個http server
func (h *Handler) Run() {log.Infof("Listening on %s", h.options.ListenAddress)server := &http.Server{Addr: h.options.ListenAddress,Handler: h.router,ErrorLog: log.NewErrorLogger(),ReadTimeout: h.options.ReadTimeout,}listener, err := net.Listen("tcp", h.options.ListenAddress)if err != nil {h.listenErrCh <- err} else {limitedListener := netutil.LimitListener(listener, h.options.MaxConnections)h.listenErrCh <- server.Serve(limitedListener)} }這個里面的h.router就是上面注冊的router,這樣就可以做http的分發(fā)了。
總結(jié)
以上是生活随笔為你收集整理的Prometheus 实战于源码分析之webHandler的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 内部类和设计模式
- 下一篇: MATLAB虚数矩阵不可随意转置