Simple API server functionality

Implement external request to API server health check and status query, return the response result

1. Internal function of state monitoring of API server

It can be obtained by calling internal functions through external API interfaces

  1. Current server health status
  2. Server hard disk
  3. CPU
  4. Memory usage

Take the internal function of memory status detection as an example

func RAMCheck(c *gin.Context) {
	u, _ := mem.VirtualMemory()

        // Get the current memory usage
	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"

        // Returns health information based on the current memory status
	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)
}
Copy the code

2. Load the status monitoring route of the API server

This block defines a group called SD, under which the /health, /disk, / CPU, and/RAM HTTP paths are registered and routed to sd.HealthCheck, sd.DiskCheck, sD. CPUCheck, and sD. RAMCheck functions respectively.

This group is mainly used to respond to external requests through the API interface. Users can call corresponding built-in functions through the API interface to obtain information about the API server health status, server hard disk, CPU and memory usage

// Load loads the middlewares, routes, handlers.
func Load(g *gin.Engine, mw ... gin.HandlerFunc) *gin.Engine {
	// Middlewares.
        // Set the response header
	g.Use(gin.Recovery())
	g.Use(middleware.NoCache)
	g.Use(middleware.Options)
	g.Use(middleware.Secure)
	g.Use(mw...)
	// 404 Handler.
        / / 404 set
	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
}
Copy the code

3. Program entry

The program entry is loaded by route first, and then the self-checker is added to Apiserver.

The self-inspection procedure works by: Before starting the HTTP port, go a pingServer coroutine. After starting the HTTP port, the coroutine continuously pings/SD /health. If the number of failures exceeds a certain number, the health status of the server is abnormal and the HTTP server process is terminated. The self-check ensures that the API server is in a healthy state after startup.

func main(a) {
	// 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(a) {
		iferr := 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(a) 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.")}Copy the code