簡單API服務器功能
實現外部請求對API 服務器健康檢查和狀態查詢,返回響應結果
1.API服務器的狀態監測
以內存狀態檢測為例,獲取當前服務器的健康狀況、服務器硬盤、CPU 和內存使用量
func RAMCheck(c *gin.Context) {u, _ := mem.VirtualMemory()//獲取當前內存占用量usedMB := int(u.Used) / MBusedGB := int(u.Used) / GBtotalMB := int(u.Total) / MBtotalGB := int(u.Total) / GBusedPercent := int(u.UsedPercent)status := http.StatusOKtext := "OK"//根據當前內存狀態,返回健康信息if usedPercent >= 95 {status = http.StatusInternalServerErrortext = "CRITICAL"} else if usedPercent >= 90 {status = http.StatusTooManyRequeststext = "WARNING"}message := fmt.Sprintf("%s - Free space: %dMB (%dGB) / %dMB (%dGB) | Used: %d%%", text, usedMB, usedGB, totalMB, totalGB, usedPercent)c.String(status, "\n"+message)
}
2.加載路由
該代碼塊定義了一個叫 sd 的分組,在該分組下注冊了 /health、/disk、/cpu、/ram HTTP 路徑,分別路由到 sd.HealthCheck、sd.DiskCheck、sd.CPUCheck、sd.RAMCheck 函數。sd 分組主要用來檢查 API Server 的狀態:健康狀況、服務器硬盤、CPU 和內存使用量
// Load loads the middlewares, routes, handlers.
func Load(g *gin.Engine, mw ...gin.HandlerFunc) *gin.Engine {// Middlewares.//設置響應頭g.Use(gin.Recovery())g.Use(middleware.NoCache)g.Use(middleware.Options)g.Use(middleware.Secure)g.Use(mw...)// 404 Handler.//404設置g.NoRoute(func(c *gin.Context) {c.String(http.StatusNotFound, "The incorrect API route.")})// The health check handlerssvcd := g.Group("/sd"){svcd.GET("/health", sd.HealthCheck)svcd.GET("/disk", sd.DiskCheck)svcd.GET("/cpu", sd.CPUCheck)svcd.GET("/ram", sd.RAMCheck)}return g
}
3.程序入口
程序入口先進行路由的加載,隨后在 apiserver 中也添加自檢程序,在啟動 HTTP 端口前 go 一個 pingServer 協程,啟動 HTTP 端口后,該協程不斷地 ping /sd/health 路徑,如果失敗次數超過一定次數,則終止 HTTP 服務器進程。通過自檢可以最大程度地保證啟動后的 API 服務器處于健康狀態。
func main() {// Create the Gin engine.g := gin.New()middlewares := []gin.HandlerFunc{}// Routes.router.Load(// Cores.g,// Middlwares.middlewares...,)// Ping the server to make sure the router is working.go func() {if err := pingServer(); err != nil {log.Fatal("The router has no response, or it might took too long to start up.", err)}log.Print("The router has been deployed successfully.")}()log.Printf("Start to listening the incoming requests on http address: %s", ":8080")log.Printf(http.ListenAndServe(":8080", g).Error())
}// pingServer pings the http server to make sure the router is working.
func pingServer() error {for i := 0; i < 2; i++ {// Ping the server by sending a GET request to `/health`.resp, err := http.Get("http://127.0.0.1:8080" + "/sd/health")if err == nil && resp.StatusCode == 200 {return nil}// Sleep for a second to continue the next ping.log.Print("Waiting for the router, retry in 1 second.")time.Sleep(time.Second)}return errors.New("Cannot connect to the router.")
}