简单API服务器功能
实现外部请求对API 服务器健康检查和状态查询,返回响应结果
1.API服务器的状态监测
以内存状态检测为例,获取当前服务器的健康状况、服务器硬盘、CPU 和内存使用量
func RAMCheck(c *gin.Context) {
u, _ := mem.VirtualMemory()
//获取当前内存占用量
usedMB := int(u.Used) / MB
usedGB := int(u.Used) / GB
totalMB := int(u.Total) / MB
totalGB := int(u.Total) / GB
usedPercent := int(u.UsedPercent)
status := http.StatusOK
text := "OK"
//根据当前内存状态,返回健康信息
if usedPercent >= 95 {
status = http.StatusInternalServerError
text = "CRITICAL"
} else if usedPercent >= 90 {
status = http.StatusTooManyRequests
text = "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 handlers
svcd := 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.")
}