mirror of
https://github.com/DullJZ/s3-balance.git
synced 2026-09-09 09:56:39 +08:00
health check to metrics
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
package health
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
)
|
||||
|
||||
// S3Target S3健康检查目标
|
||||
type S3Target struct {
|
||||
ID string
|
||||
Bucket string
|
||||
Endpoint string
|
||||
Client *s3.Client
|
||||
}
|
||||
|
||||
// GetID 实现 Target 接口
|
||||
func (t *S3Target) GetID() string {
|
||||
return t.ID
|
||||
}
|
||||
|
||||
// GetType 实现 Target 接口
|
||||
func (t *S3Target) GetType() string {
|
||||
return "s3"
|
||||
}
|
||||
|
||||
// GetEndpoint 实现 Target 接口
|
||||
func (t *S3Target) GetEndpoint() string {
|
||||
return t.Endpoint
|
||||
}
|
||||
|
||||
// S3Checker S3健康检查器
|
||||
type S3Checker struct {
|
||||
config Config
|
||||
}
|
||||
|
||||
// NewS3Checker 创建S3健康检查器
|
||||
func NewS3Checker(config Config) *S3Checker {
|
||||
if config.Interval == 0 {
|
||||
config.Interval = 30 * time.Second
|
||||
}
|
||||
if config.Timeout == 0 {
|
||||
config.Timeout = 5 * time.Second
|
||||
}
|
||||
if config.Retries == 0 {
|
||||
config.Retries = 1
|
||||
}
|
||||
|
||||
return &S3Checker{
|
||||
config: config,
|
||||
}
|
||||
}
|
||||
|
||||
// Check 执行S3健康检查
|
||||
func (c *S3Checker) Check(ctx context.Context, target Target) Status {
|
||||
s3Target, ok := target.(*S3Target)
|
||||
if !ok {
|
||||
return Status{
|
||||
Healthy: false,
|
||||
LastChecked: time.Now(),
|
||||
Message: "invalid target type for S3 checker",
|
||||
Error: fmt.Errorf("expected *S3Target, got %T", target),
|
||||
}
|
||||
}
|
||||
|
||||
// 创建带超时的context
|
||||
checkCtx, cancel := context.WithTimeout(ctx, c.config.Timeout)
|
||||
defer cancel()
|
||||
|
||||
var lastErr error
|
||||
for i := 0; i < c.config.Retries; i++ {
|
||||
if i > 0 {
|
||||
// 重试前等待
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return Status{
|
||||
Healthy: false,
|
||||
LastChecked: time.Now(),
|
||||
Message: "health check cancelled",
|
||||
Error: ctx.Err(),
|
||||
}
|
||||
case <-time.After(time.Second):
|
||||
}
|
||||
}
|
||||
|
||||
err := c.performCheck(checkCtx, s3Target)
|
||||
if err == nil {
|
||||
return Status{
|
||||
Healthy: true,
|
||||
LastChecked: time.Now(),
|
||||
Message: fmt.Sprintf("S3 bucket %s is healthy", s3Target.Bucket),
|
||||
}
|
||||
}
|
||||
lastErr = err
|
||||
}
|
||||
|
||||
return Status{
|
||||
Healthy: false,
|
||||
LastChecked: time.Now(),
|
||||
Message: fmt.Sprintf("S3 bucket %s is unhealthy after %d retries", s3Target.Bucket, c.config.Retries),
|
||||
Error: lastErr,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *S3Checker) performCheck(ctx context.Context, target *S3Target) error {
|
||||
switch c.config.Strategy {
|
||||
case StrategyDetailed:
|
||||
return c.performDetailedCheck(ctx, target)
|
||||
default:
|
||||
return c.performSimpleCheck(ctx, target)
|
||||
}
|
||||
}
|
||||
|
||||
// performSimpleCheck 执行简单健康检查(轻量级)
|
||||
func (c *S3Checker) performSimpleCheck(ctx context.Context, target *S3Target) error {
|
||||
// 尝试列出1个对象,这是最轻量级的检查方式
|
||||
_, err := target.Client.ListObjectsV2(ctx, &s3.ListObjectsV2Input{
|
||||
Bucket: aws.String(target.Bucket),
|
||||
MaxKeys: aws.Int32(1),
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// performDetailedCheck 执行详细健康检查(包含更多验证)
|
||||
func (c *S3Checker) performDetailedCheck(ctx context.Context, target *S3Target) error {
|
||||
// 先执行简单检查
|
||||
if err := c.performSimpleCheck(ctx, target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 可以添加更多详细检查,比如:
|
||||
// 1. 检查存储桶策略
|
||||
// 2. 测试写入权限(创建并删除测试对象)
|
||||
// 3. 检查存储桶版本控制状态
|
||||
// 4. 测量响应时间等性能指标
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetInterval 获取检查间隔
|
||||
func (c *S3Checker) GetInterval() time.Duration {
|
||||
return c.config.Interval
|
||||
}
|
||||
|
||||
// GetTimeout 获取检查超时时间
|
||||
func (c *S3Checker) GetTimeout() time.Duration {
|
||||
return c.config.Timeout
|
||||
}
|
||||
Reference in New Issue
Block a user