golang简易可扩展的健康检查插件库health的使用

Golang简易可扩展的健康检查插件库health的使用

简介

这是一个易于使用、可扩展的Go应用程序健康检查库。

Build Status Go Report Card GoDoc

示例代码

package main

import (
    "net/http"
    "database/sql"
    "time"

    "github.com/dimiro1/health"
    "github.com/dimiro1/health/url"
    "github.com/dimiro1/health/db"
    "github.com/dimiro1/health/redis"
    _ "github.com/go-sql-driver/mysql"
)

func main() {
    database, _ := sql.Open("mysql", "/")
    mysql := db.NewMySQLChecker(database)
    timeout := 5 * time.Second
    
    // 创建复合检查器
    companies := health.NewCompositeChecker()
    companies.AddChecker("Microsoft", url.NewChecker("https://www.microsoft.com/"))
    companies.AddChecker("Oracle", url.NewChecker("https://www.oracle.com/"))
    companies.AddChecker("Google", url.NewChecker("https://www.google.com/"))

    // 创建健康检查处理器
    handler := health.NewHandler()
    handler.AddChecker("Go", url.NewCheckerWithTimeout("https://golang.org/", timeout))
    handler.AddChecker("Big Companies", companies)
    handler.AddChecker("MySQL", mysql)
    handler.AddChecker("Redis", redis.NewChecker("tcp", ":6379"))

    // 设置HTTP路由
    http.Handle("/health/", handler)
    http.ListenAndServe(":8080", nil)
}

健康检查响应

当所有检查都正常时,服务器会返回HTTP状态码200 OK和如下JSON响应:

{
    "Big Companies": {
        "Google": {
            "code": 200,
            "status": "UP"
        },
        "Microsoft": {
            "code": 200,
            "status": "UP"
        },
        "Oracle": {
            "code": 200,
            "status": "UP"
        },
        "status": "UP"
    },
    "Go": {
        "code": 200,
        "status": "UP"
    },
    "MySQL": {
        "status": "UP",
        "version": "10.1.9-MariaDB"
    },
    "Redis": {
        "status": "UP",
        "version": "3.0.5"
    },
    "status": "UP"
}

当有检查失败时,服务器会返回HTTP状态码503 Service Unavailable和如下JSON响应:

{
    "Big Companies": {
        "Google": {
            "code": 200,
            "status": "UP"
        },
        "Microsoft": {
            "code": 200,
            "status": "UP"
        },
        "Oracle": {
            "code": 200,
            "status": "UP"
        },
        "status": "UP"
    },
    "Go": {
        "code": 200,
        "status": "UP"
    },
    "MySQL": {
        "status": "DOWN",
        "error": "Error 1044: Access denied for user ''@'localhost' to database 'invalid-database'",
    },
    "Redis": {
        "status": "UP",
        "version": "3.0.5"
    },
    "status": "DOWN"
}

实现自定义检查器

要实现自定义检查器,只需创建一个满足health.Checker接口的类型:

type Checker interface {
    Check() Health
}

示例:磁盘空间检查器(仅Unix系统)

package main

import (
    "syscall"
    "os"
)

type DiskSpaceChecker struct {
    Dir       string
    Threshold uint64
}

func NewDiskSpaceChecker(dir string, threshold uint64) DiskSpaceChecker {
    return DiskSpaceChecker{Dir: dir, Threshold: threshold}
}

func (d DiskSpaceChecker) Check() health.Health {
    health := health.NewHealth()

    var stat syscall.Statfs_t

    wd, err := os.Getwd()

    if err != nil {
        health.Down().AddInfo("error", err.Error()) // 为什么检查失败
        return health
    }

    syscall.Statfs(wd, &stat)

    diskFreeInBytes := stat.Bavail * uint64(stat.Bsize)

    if diskFreeInBytes < d.Threshold {
        health.Down()
    } else {
        health.Up()
    }

    health.
        AddInfo("free", diskFreeInBytes).
        AddInfo("threshold", d.Threshold)

    return health
}

已实现的健康检查指标

健康检查 描述
url.Checker 检查与某个URL的连接 github.com/dimiro1/health/url
db.Checker 检查数据库连接 github.com/dimiro1/health/db
redis.Checker 检查Redis连接 github.com/dimiro1/health/redis

安装

go get github.com/dimiro1/health

测试依赖

go get gopkg.in/DATA-DOG/go-sqlmock.v1
go get github.com/rafaeljusto/redigomock

或者使用-t标志安装:

go get -t github.com/dimiro1/health

重要提示

JSON中的status键优先级高于检查器添加的status键,因此如果某个检查器向JSON添加了status键,它将不会被渲染。


更多关于golang简易可扩展的健康检查插件库health的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang简易可扩展的健康检查插件库health的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang健康检查插件库health使用指南

health是一个轻量级、可扩展的Golang健康检查库,可以帮助你构建服务健康检查系统。下面我将详细介绍其使用方法。

基本使用

首先安装health库:

go get github.com/alexliesenfeld/health

简单示例

package main

import (
	"fmt"
	"net/http"
	"time"
	
	"github.com/alexliesenfeld/health"
)

func main() {
	// 创建健康检查器
	checker := health.NewChecker(
		// 设置检查超时时间
		health.WithTimeout(10*time.Second),
		
		// 添加自定义检查项
		health.WithCheck(health.Check{
			Name: "some-check",
			Check: func() error {
				// 这里实现你的检查逻辑
				// 返回nil表示健康,返回error表示不健康
				return nil
			},
		}),
	)
	
	// 创建HTTP健康检查端点
	http.Handle("/health", health.NewHandler(checker))
	
	// 启动HTTP服务器
	fmt.Println("Server started at :8080")
	http.ListenAndServe(":8080", nil)
}

核心功能

1. 内置检查器

health提供了一些内置检查器:

checker := health.NewChecker(
	// 内存使用检查
	health.WithSystemMemoryCheck(0.9), // 内存使用超过90%报错
	
	// 磁盘空间检查
	health.WithSystemDiskCheck("/", 0.9), // 根目录使用超过90%报错
	
	// Goroutine数量检查
	health.WithSystemGoroutineCountCheck(1000), // 超过1000个goroutine报错
)

2. 自定义检查项

checker := health.NewChecker(
	health.WithCheck(health.Check{
		Name: "database",
		Check: func() error {
			// 实现数据库连接检查
			db, err := sql.Open("mysql", "user:password@/dbname")
			if err != nil {
				return err
			}
			return db.Ping()
		},
		Timeout: 5 * time.Second, // 单独设置超时
		CacheDuration: 10 * time.Second, // 缓存检查结果10秒
	}),
)

3. 周期性检查

checker := health.NewChecker(
	health.WithPeriodicCheck(15*time.Second, 5*time.Second, health.Check{
		Name: "external-service",
		Check: func() error {
			// 检查外部服务
			resp, err := http.Get("https://api.example.com/status")
			if err != nil {
				return err
			}
			defer resp.Body.Close()
			if resp.StatusCode != http.StatusOK {
				return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
			}
			return nil
		},
	}),
)

高级功能

1. 自定义响应格式

http.Handle("/health", health.NewHandler(
	health.WithChecker(checker),
	health.WithResultWriter(&health.JSONResultWriter{
		PrettyPrint: true,
	}),
))

2. 添加元数据

checker := health.NewChecker(
	health.WithComponent(health.Component{
		Name:    "my-service",
		Version: "1.0.0",
	}),
	health.WithCustomDetails("environment", "production"),
)

3. 状态聚合

checker := health.NewChecker(
	health.WithStatusListener(func(ctx context.Context, state health.CheckerState) {
		// 当健康状态变化时触发
		if state.Status == health.StatusDown {
			log.Printf("Service is down! Details: %v", state.Details)
		}
	}),
)

完整示例

package main

import (
	"context"
	"fmt"
	"net/http"
	"time"
	
	"github.com/alexliesenfeld/health"
)

func main() {
	// 创建健康检查器
	checker := health.NewChecker(
		// 基本配置
		health.WithTimeout(10*time.Second),
		health.WithComponent(health.Component{
			Name:    "order-service",
			Version: "1.2.0",
		}),
		
		// 系统资源检查
		health.WithSystemMemoryCheck(0.8),
		health.WithSystemDiskCheck("/", 0.9),
		
		// 自定义检查项
		health.WithCheck(health.Check{
			Name: "database",
			Check: func() error {
				// 模拟数据库检查
				time.Sleep(100 * time.Millisecond)
				return nil
			},
		}),
		
		// 周期性检查外部服务
		health.WithPeriodicCheck(30*time.Second, 5*time.Second, health.Check{
			Name: "payment-gateway",
			Check: func() error {
				// 模拟外部服务检查
				time.Sleep(200 * time.Millisecond)
				return nil
			},
		}),
		
		// 状态监听
		health.WithStatusListener(func(ctx context.Context, state health.CheckerState) {
			fmt.Printf("Health status changed to: %s\n", state.Status)
		}),
	)
	
	// 创建HTTP健康检查端点
	http.Handle("/health", health.NewHandler(checker))
	
	// 启动服务器
	fmt.Println("Server started at :8080")
	if err := http.ListenAndServe(":8080", nil); err != nil {
		panic(err)
	}
}

扩展建议

  1. 集成到现有框架:可以轻松集成到Gin、Echo等Web框架中
  2. 自定义检查器:实现health.Checkable接口创建可复用的检查器
  3. 监控集成:将健康状态变化发送到Prometheus、Datadog等监控系统
  4. 优雅停机:在健康检查失败时触发优雅停机流程

health库设计简洁但功能强大,非常适合微服务架构中的健康检查需求。通过合理配置检查项和阈值,可以全面监控服务的健康状况。

回到顶部