• API 服务器健康状态自检


    0. 本节核心内容

    • API 服务器健康检查和状态查询

    • 编译并测试 API

    本小节源码下载路径:demo02

    1. 服务器健康有哪些?

    思考: 服务器健康有哪些?如何检查?

    • 磁盘空间

    • CPU状态

    • MEM状态

    • 服务状态等

    2. 定义路由分组用于服务器健康检查

    由于后期我们会实现很多路由对应的处理函数,如果量大的话,router文件会变得非常大

    因此,我们也可以将处理函数放到handler目录中

    ”apiserver/handler/sd“ 此目录将用于保存服务器检查相关处理函数

    注意:短小的处理函数可以直接编写匿名函数放在router中,长函数建议拆分

    apiserver/router/router.go

    1.   // 加载模块-处理函数模块化
    2.   "apiserver/handler/sd"
    3.   // 在Load函数中添加    
    4.   // -modify here- 添加健康检查的handler
    5.   svcd := g.Group("/sd")
    6.   {  
    7.       svcd.GET("/health", sd.HealthCheck)
    8.       svcd.GET("/disk", sd.DiskCheck)
    9.       svcd.GET("/cpu", sd.CPUCheck)
    10.       svcd.GET("/ram", sd.RAMCheck)
    11.   }

            该代码块定义了一个叫 sd 的路由分组,在该分组下注册了 /health/disk/cpu/ram HTTP 路径,分别路由到 sd.HealthChecksd.DiskChecksd.CPUChecksd.RAMCheck 函数。

            sd 分组主要用来检查 API Server 的状态:健康状况、服务器硬盘、CPU 和内存使用量。

       main() 函数通过调用 router.Load 函数来加载路由,路由映射到具体的处理函数

    3. 服务器健康检查实现

    apiserver/handler/sd/check.go

    编写几个检查函数

    1. package sd
    2. import (
    3. "fmt"
    4. "net/http"
    5. "github.com/gin-gonic/gin"
    6. "github.com/shirou/gopsutil/cpu"
    7. "github.com/shirou/gopsutil/disk"
    8. "github.com/shirou/gopsutil/load"
    9. "github.com/shirou/gopsutil/mem"
    10. )
    11. // 定义常量
    12. const (
    13. B = 1
    14. KB = 1024 * B
    15. MB = 1024 * KB
    16. GB = 1024 * MB
    17. )
    18. // HealthCheck shows `OK` as the ping-pong result.
    19. func HealthCheck(c *gin.Context) {
    20. message := "OK"
    21. // http.StatusOK => 所有HTTP状态码都对应到一个名字 (源码)
    22. c.String(http.StatusOK, "\n"+message)
    23. }
    24. // DiskCheck checks the disk usage.
    25. func DiskCheck(c *gin.Context) {
    26.   // 可查看disk.Usage的源代码,此处有2个返回值,*UsageStat, erro
    27. u, _ := disk.Usage("/")
    28. usedMB := int(u.Used) / MB
    29. usedGB := int(u.Used) / GB
    30. totalMB := int(u.Total) / MB
    31. totalGB := int(u.Total) / GB
    32. usedPercent := int(u.UsedPercent)
    33. status := http.StatusOK
    34. text := "OK"
    35. if usedPercent >= 95 {
    36. status = http.StatusInternalServerError
    37. text = "CRITICAL"
    38. } else if usedPercent >= 90 {
    39. status = http.StatusTooManyRequests
    40. text = "WARNING"
    41. }
    42. message := fmt.Sprintf("%s - Free space: %dMB (%dGB) / %dMB (%dGB) | Used: %d%%", text, usedMB, usedGB, totalMB, totalGB, usedPercent)
    43. c.String(status, "\n"+message)
    44. }
    45. // CPUCheck checks the cpu usage.
    46. func CPUCheck(c *gin.Context) {
    47. cores, _ := cpu.Counts(false)
    48. a, _ := load.Avg()
    49. l1 := a.Load1
    50. l5 := a.Load5
    51. l15 := a.Load15
    52. status := http.StatusOK
    53. text := "OK"
    54. if l5 >= float64(cores-1) {
    55. status = http.StatusInternalServerError
    56. text = "CRITICAL"
    57. } else if l5 >= float64(cores-2) {
    58. status = http.StatusTooManyRequests
    59. text = "WARNING"
    60. }
    61. message := fmt.Sprintf("%s - Load average: %.2f, %.2f, %.2f | Cores: %d", text, l1, l5, l15, cores)
    62. c.String(status, "\n"+message)
    63. }
    64. // RAMCheck checks the disk usage.
    65. func RAMCheck(c *gin.Context) {
    66. u, _ := mem.VirtualMemory()
    67. usedMB := int(u.Used) / MB
    68. usedGB := int(u.Used) / GB
    69. totalMB := int(u.Total) / MB
    70. totalGB := int(u.Total) / GB
    71. usedPercent := int(u.UsedPercent)
    72. status := http.StatusOK
    73. text := "OK"
    74. if usedPercent >= 95 {
    75. status = http.StatusInternalServerError
    76. text = "CRITICAL"
    77. } else if usedPercent >= 90 {
    78. status = http.StatusTooManyRequests
    79. text = "WARNING"
    80. }
    81. message := fmt.Sprintf("%s - Free space: %dMB (%dGB) / %dMB (%dGB) | Used: %d%%", text, usedMB, usedGB, totalMB, totalGB, usedPercent)
    82. c.String(status, "\n"+message)
    83. }

    拓展知识:拓展知识:Go变量与内置数据类型 => 常量的定义、结构体

    拓展知识:Go函数 => 错误处理

    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:8000/sd/health
      ​
      OK
    • ApiPost测试:

    6. 启动apiserver时自检

    上面我们已经实现了几个接口用于获取服务器状态,但是,它需要我们主动访问才能获取状态,那么我们如何能在有问题时,直接收到提醒呢?

    • 定时任务/监控系统:编写监控脚本,有问题时提醒(邮件/短信/电话/微信/钉钉...)

      这部分在Linux部分会详细学习...

    • 启动服务时:主动检查,有问题直接停掉服务,提醒管理员

      有时候 API 进程起来不代表 API 服务器正常,如API 进程存在,但是服务器却不能对外提供服务。因此在启动 API 服务器时,如果能够最后做一个自检会更好些。

    在 apiserver 中添加了自检程序,通过自检可以最大程度地保证启动后的 API 服务器处于健康状态。

    apiserver/main.go

    定义pingServer用于检查/sd/health是否正常访问

    1. // pingServer pings the http server to make sure the router is working.
    2. func pingServer() error {
    3. //如果函数正常运行 -》返回值nil
    4. //如果函数出错了 -》error
    5. for i := 0; i < 10; i++ {
    6. // 请求/sd/health => Get返回值有两个
    7. resp, err := http.Get("http://127.0.0.1:8000" + "/sd/health")
    8. log.Print("Waiting for the router, retry in 1 second.")
    9. // 如果返回200,则表示启动成功,直接返回nil
    10. if err == nil && resp.StatusCode == 200 {
    11. return nil
    12. }
    13. // 否则1秒后重试
    14. log.Print("Waiting for the router, retry in 1 second.")
    15. time.Sleep(time.Second)
    16. }
    17. // 尝试10次,均失败则返回一个错误
    18. return errors.New("Cannot connect to the router.")
    19. }
    • pingServer() 函数中,http.Gethttp://127.0.0.1:8080/sd/health 发送 HTTP GET 请求

    • 如果函数正确执行并且返回的 HTTP StatusCode 为 200,则说明 API 服务器可用。

    • 如果超过指定次数,服务还是不能访问,pingServer会 返回errors,表示API服务器不可用。

    拓展知识:标准库-log:Go语言标准库之log - 二十三岁的有德 - 博客园

    拓展知识:标准库-time: https://www.jianshu.com/p/9d5636d34f17

    拓展知识:标准库-常用的http请求操作: golang常用的http请求操作 - 腾讯云开发者社区-腾讯云

    apiserver/main.go

    调用pingServer检查服务是否正常

    1. func main() {
    2. ...
    3. // 调用协程函数,检查服务健康状态
    • 在启动 HTTP 端口前 go 一个 pingServer 协程(后台并行执行的一个任务)

    • 启动 HTTP 端口后,该协程不断地 ping /sd/health 路径

    • 如果成功,则输出部署成功提示

    • 如果失败次数超过一定次数,则终止 HTTP 服务器进程

    拓展知识:go协程:https://www.jianshu.com/p/4ae2281927d7

    7. 测试

  • 相关阅读:
    使用【Blob、Base64】两种方式显示【文本、图片、视频】 & 使用 video 组件播放视频
    WPF中可冻结对象
    ShardingSphere集成SpringBoot实现分库分表(三)-数据分片概述
    安装torch113、cuda116并运行demo【Transformer】
    node分布式(小鹿线)
    商用短链平台_第4章_功能需求介绍和微服务拆分讲解
    ESP8266-Arduino编程实例-APDS-9930环境光和趋近感器驱动
    Gbase数据库
    CCF CSP认证 历年题目自练 Day22
    常用的网络攻击手段
  • 原文地址:https://blog.csdn.net/a1991376352/article/details/126028978