目录
RESTful API服务器
1. REST Web 框架选择
// 加载模块-处理函数模块化
"apiserver/handler/sd"
// 在Load函数中添加
// -modify here- 添加健康检查的handler
svcd := g.Group("/sd")
{
svcd.GET("/health", sd.HealthCheck)
svcd.GET("/disk", sd.DiskCheck)
svcd.GET("/cpu", sd.CPUCheck)
svcd.GET("/ram", sd.RAMCheck)
}
/health/disk/cpu/ramsd.HealthChecksd.DiskChecksd.CPUChecksd.RAMCheckmain()router.Load
3. 服务器健康检查实现
apiserver/handler/sd/check.go
编写几个检查函数
package sd
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
"github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/disk"
"github.com/shirou/gopsutil/load"
"github.com/shirou/gopsutil/mem"
)
// 定义常量
const (
B = 1
KB = 1024 * B
MB = 1024 * KB
GB = 1024 * MB
)
// HealthCheck shows `OK` as the ping-pong result.
func HealthCheck(c *gin.Context) {
message := "OK"
// http.StatusOK => 所有HTTP状态码都对应到一个名字 (源码)
c.String(http.StatusOK, "\n"+message)
}
// DiskCheck checks the disk usage.
func DiskCheck(c *gin.Context) {
// 可查看disk.Usage的源代码,此处有2个返回值,*UsageStat, erro
u, _ := disk.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"
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)
}
// CPUCheck checks the cpu usage.
func CPUCheck(c *gin.Context) {
cores, _ := cpu.Counts(false)
a, _ := load.Avg()
l1 := a.Load1
l5 := a.Load5
l15 := a.Load15
status := http.StatusOK
text := "OK"
if l5 >= float64(cores-1) {
status = http.StatusInternalServerError
text = "CRITICAL"
} else if l5 >= float64(cores-2) {
status = http.StatusTooManyRequests
text = "WARNING"
}
message := fmt.Sprintf("%s - Load average: %.2f, %.2f, %.2f | Cores: %d", text, l1, l5, l15, cores)
c.String(status, "\n"+message)
}
// RAMCheck checks the disk usage.
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)
}
4. 安装依赖并测试
mod tidy 会自动检查依赖并下载需要的内容,非常nice
```
go mod tidy
```
这里主要是安装了:
```
go get github.com/shirou/gopsutil/cpu
go get github.com/shirou/gopsutil/disk
go get github.com/shirou/gopsutil/load
go get github.com/shirou/gopsutil/mem
```
5. 测试
命令行测试:
# curl http://localhost:8090/sd/health
OK
ApiPost测试:
6. 启动apiserver时自检
上面我们已经实现了几个接口用于获取服务器状态,但是,它需要我们主动访问才能获取状态,那么我们如何能在有问题时,直接收到提醒呢?定时任务/监控系统:编写监控脚本,有问题时提醒
启动服务时:主动检查,有问题直接停掉服务,提醒管理员
有时候 API 进程起来不代表 API 服务器正常,如API 进程存在,但是服务器却不能对外提供服务。因此在启动 API 服务器时,如果能够最后做一个自检会更好些。
在 apiserver 中添加了自检程序,通过自检可以最大程度地保证启动后的 API 服务器处于健康状态。
apiserver/main.go
定义pingServer用于检查/sd/health是否正常访问
// pingServer pings the http server to make sure the router is working.
func pingServer() error {
for i := 0; i < 10; i++ {
// 请求/sd/health => Get返回值有两个
resp, err := http.Get("http://127.0.0.1:8090" + "/sd/health")
log.Print("Waiting for the router, retry in 1 second.")
// 如果返回200,则表示启动成功,直接返回nil
if err == nil && resp.StatusCode == 200 {
return nil
}
// 否则1秒后重试
log.Print("Waiting for the router, retry in 1 second.")
time.Sleep(time.Second)
}
// 尝试10次,均失败则返回一个错误
return errors.New("Cannot connect to the router.")
}
pingServer()http.Gethttp://127.0.0.1:8080/sd/healthpingServer
apiserver/main.go
调用pingServer检查服务是否正常
func main() {
...
// 调用协程函数,检查服务健康状态
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.")
}()
// 让应用运行在本地服务器上,默认监听端口是 8080
g.Run(":8090") // listen and serve on 0.0.0.0:8090
}
pingServer/sd/health
7. 测试