golang简单灵活的Go应用健康检查插件库health的使用

Golang简单灵活的Go应用健康检查插件库health的使用

简介

Health是一个简单灵活的Go语言健康检查库,它提供了一个http.Handler作为健康检查端点。这个库不仅可以返回HTTP 200状态码,还能检查所有依赖服务的可用性,并在HTTP响应中包含聚合的健康结果和每个组件的详细状态信息。

安装

go get github.com/alexliesenfeld/health

基本示例

下面是一个展示基本功能的完整示例:

package main

import (
	"context"
	"database/sql"
	"fmt"
	"github.com/alexliesenfeld/health"
	_ "github.com/mattn/go-sqlite3"
	"log"
	"net/http"
	"time"
)

func main() {
	db, _ := sql.Open("sqlite3", "simple.sqlite")
	defer db.Close()

	// 创建一个新的Checker
	checker := health.NewChecker(
		
		// 设置缓存TTL为1秒(默认值)
		health.WithCacheDuration(1*time.Second),

		// 配置所有检查的全局超时时间为10秒
		health.WithTimeout(10*time.Second),

		// 检查数据库连接是否正常
		// 每个HTTP请求都会执行这个检查函数
		health.WithCheck(health.Check{
			Name:    "database",      // 唯一的检查名称
			Timeout: 2 * time.Second, // 检查特定的超时时间
			Check:   db.PingContext,
		}),

		// 这个检查会每15秒执行一次,初始延迟3秒
		// 不会为每个HTTP请求执行检查函数
		health.WithPeriodicCheck(15*time.Second, 3*time.Second, health.Check{
			Name: "search",
			// 检查函数检查组件健康状况
			// 如果返回错误,则认为组件不可用("down")
			// 上下文包含根据配置超时设置的截止时间
			Check: func(ctx context.Context) error {
				return fmt.Errorf("this makes the check fail")
			},
		}),

		// 设置状态监听器,当健康状态变化时调用
		health.WithStatusListener(func(ctx context.Context, state health.CheckerState) {
			log.Println(fmt.Sprintf("health status changed to %s", state.Status))
		}),
	)

	// 创建一个新的健康检查http.Handler,返回JSON格式的健康状态
	http.Handle("/health", health.NewHandler(checker))
	log.Fatalln(http.ListenAndServe(":3000", nil))
}

响应示例

由于search组件不可用,请求curl http://localhost:3000/health会返回HTTP状态码503 (Service Unavailable),以及以下JSON响应体:

{
  "status": "down",
  "details": {
    "database": {
      "status": "up",
      "timestamp": "2021-07-01T08:05:14.603364Z"
    },
    "search": {
      "status": "down",
      "timestamp": "2021-07-01T08:05:08.522685Z",
      "error": "this makes the check fail"
    }
  }
}

同步与异步检查

同步检查

每个HTTP请求都会触发健康检查,并等待所有检查函数完成后返回聚合的健康结果。可以使用WithCheck配置选项配置同步检查。

异步检查

异步(周期性)健康检查在固定时间表上执行检查函数。使用这种方法,健康状态总是从本地缓存中读取,该缓存在后台定期更新。这允许即时响应HTTP请求,而无需等待检查函数完成。可以使用WithPeriodicCheck配置选项配置异步检查。

缓存

健康检查结果会被缓存以避免向检查的服务发送过多请求,并减轻"拒绝服务"攻击。默认TTL设置为1秒。如果想完全禁用缓存,可以使用health.WithDisabledCache()配置选项。

状态变化监听

可以配置监听函数,当整体/聚合健康状态或特定组件状态发生变化时调用。

示例

health.WithPeriodicCheck(5*time.Second, 0, health.Check{
    Name:   "search",
    Check:  myCheckFunc,
    StatusListener: func (ctx context.Context, name string, state CheckState) ) {
	    log.Printf("status of component '%s' changed to %s", name, state.Status)
    },
}),

health.WithStatusListener(func (ctx context.Context, state CheckerState)) {
    log.Printf("overall system health status changed to %s", state.Status)
}),

中间件和拦截器

中间件

可以拦截所有Checker.Check调用,对应于每个传入的HTTP请求。允许访问检查相关信息并在发送HTTP响应前对检查结果进行后处理。

拦截器

可以拦截对检查函数的所有调用。这对于需要可重用并需要访问检查状态信息的跨功能代码很有用。

与其他库的兼容性

这个库设计上可以轻松重用现有解决方案,以下是一些兼容的检查实现:

  1. github.com/hellofresh/health-go
  2. github.com/etherlabsio/healthcheck
  3. github.com/heptiolabs/healthcheck
  4. github.com/InVisionApp/go-health

许可证

health是自由软件:您可以根据MIT公共许可证的条款重新分发和/或修改它。


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

1 回复

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


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

health是一个简单灵活的Go应用健康检查库,可以帮助你监控应用的各种健康指标。下面我将详细介绍它的使用方法。

安装

go get github.com/alexliesenfeld/health

基本使用

创建健康检查器

package main

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

func main() {
	// 创建健康检查器
	checker := health.NewChecker(
		// 设置检查名称
		health.WithName("my-service"),
		// 设置检查超时时间
		health.WithTimeout(5*time.Second),
		// 添加自定义检查项
		health.WithCheck(health.Check{
			Name: "database",
			Check: func() error {
				// 这里实现数据库连接检查
				return nil // 返回nil表示健康
			},
		}),
	)

	// 创建HTTP健康检查端点
	http.Handle("/health", health.NewHandler(checker))
	http.ListenAndServe(":8080", nil)
}

内置检查项

health提供了一些内置的检查项:

checker := health.NewChecker(
	// 检查HTTP服务
	health.WithHTTPCheck(health.HTTPCheckConfig{
		Name:       "api-service",
		URL:        "http://localhost:8080/api",
		Timeout:    3 * time.Second,
		StatusCode: 200,
	}),
	
	// 检查TCP连接
	health.WithTCPCheck(health.TCPCheckConfig{
		Name:    "redis",
		Address: "localhost:6379",
		Timeout: 2 * time.Second,
	}),
	
	// 检查DNS解析
	health.WithDNSCheck(health.DNSCheckConfig{
		Name:      "dns",
		Host:      "example.com",
		Timeout:   2 * time.Second,
	}),
)

高级功能

自定义响应格式

checker := health.NewChecker(
	health.WithName("custom-service"),
	health.WithCustomDetails(map[string]interface{}{
		"version": "1.0.0",
		"env":     "production",
	}),
)

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

周期性检查

checker := health.NewChecker(
	health.WithPeriodicCheck(15*time.Second, 5*time.Second, health.Check{
		Name: "background-job",
		Check: func() error {
			// 实现周期性检查逻辑
			return nil
		},
	}),
)

组合多个检查器

mainChecker := health.NewChecker(
	health.WithName("main-service"),
)

dbChecker := health.NewChecker(
	health.WithName("database"),
	health.WithCheck(health.Check{
		Name: "connection",
		Check: func() error {
			// 数据库连接检查
			return nil
		},
	}),
)

// 将dbChecker作为子检查器
mainChecker.AddChecker("db", dbChecker)

完整示例

package main

import (
	"database/sql"
	"fmt"
	"github.com/alexliesenfeld/health"
	_ "github.com/lib/pq"
	"net/http"
	"time"
)

func main() {
	// 初始化数据库连接
	db, _ := sql.Open("postgres", "user=postgres dbname=test sslmode=disable")
	
	// 创建健康检查器
	checker := health.NewChecker(
		health.WithName("order-service"),
		health.WithVersion("1.2.3"),
		health.WithTimeout(10*time.Second),
		health.WithCustomDetails(map[string]interface{}{
			"commit":  "a1b2c3d",
			"deployed": time.Now().Format(time.RFC3339),
		}),
		
		// 数据库检查
		health.WithCheck(health.Check{
			Name: "postgres",
			Check: func() error {
				return db.Ping()
			},
		}),
		
		// 外部API检查
		health.WithHTTPCheck(health.HTTPCheckConfig{
			Name:       "payment-api",
			URL:        "http://payment-service:8080/health",
			Timeout:    3 * time.Second,
			StatusCode: 200,
		}),
		
		// 周期性检查后台任务
		health.WithPeriodicCheck(30*time.Second, 5*time.Second, health.Check{
			Name: "background-processor",
			Check: func() error {
				// 检查后台处理是否正常
				return nil
			},
		}),
	)
	
	// 添加HTTP健康检查端点
	http.Handle("/health", health.NewHandler(checker))
	
	// 添加就绪检查端点(只包含关键检查项)
	http.Handle("/ready", health.NewHandler(
		health.NewChecker(
			health.WithCheck(health.Check{
				Name: "postgres",
				Check: func() error {
					return db.Ping()
				},
			}),
		),
	))
	
	fmt.Println("Server started at :8080")
	http.ListenAndServe(":8080", nil)
}

最佳实践

  1. 区分健康检查和就绪检查:

    • 健康检查(/health):检查应用所有组件
    • 就绪检查(/ready):只检查关键依赖项
  2. 为检查项设置合理的超时时间

  3. 在Kubernetes部署中:

    livenessProbe:
      httpGet:
        path: /health
        port: 8080
      initialDelaySeconds: 15
      periodSeconds: 10
      
    readinessProbe:
      httpGet:
        path: /ready
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 5
    

health库提供了简单而强大的健康检查功能,可以帮助你构建可靠的微服务应用。

回到顶部