golang实现服务熔断机制的Circuit Breaker插件库circuitbreaker的使用

golang实现服务熔断机制的Circuit Breaker插件库circuitbreaker的使用

Circuitbreaker提供了一个简单的方式在Go程序中使用熔断器模式。熔断器通常用于程序进行远程调用时,当远程调用失败或超时达到一定阈值时,熔断器会"跳闸"阻止后续调用,避免系统资源被耗尽。

安装

go get github.com/rubyist/circuitbreaker

使用示例

基本使用示例

// 创建一个在10次失败后会跳闸的熔断器
cb := circuit.NewThresholdBreaker(10)

// 订阅熔断器事件
events := cb.Subscribe()
go func() {
  for {
    e := <-events
    // 监控熔断器事件如BreakerTripped、BreakerReset、BreakerFail、BreakerReady
  }
}()

// 使用熔断器包装远程调用
cb.Call(func() error {
    // 这里执行远程调用
    // 如果失败,返回error
}, 0) // 0表示不使用超时

带超时的熔断器

// 创建一个在10次失败后会跳闸的熔断器,并设置5秒超时
cb := circuit.NewThresholdBreaker(10)

cb.Call(func() error {
  // 这里执行远程调用
  // 如果失败,返回error
}, time.Second * 5) // 5秒超时,超时算作失败

基于连续失败的熔断器

// 创建一个在10次连续失败后会跳闸的熔断器
cb := circuit.NewConsecutiveBreaker(10)

// 使用方式同上

基于错误率的熔断器

// 创建一个基于错误率的熔断器,当错误率达到95%且至少有100个样本时跳闸
cb := circuit.NewRateBreaker(0.95, 100)

// 使用方式同上

手动控制熔断器

cb := circuit.NewThresholdBreaker(10)

for {
  if cb.Ready() {
    // 熔断器未跳闸,继续执行
    err := doSomething()
    if err != nil {
      cb.Fail() // 失败计数,达到10次会跳闸
      continue
    }
    cb.Success()
  } else {
    // 熔断器处于跳闸状态
  }
}

HTTP客户端包装

// 创建一个带5秒超时和10次失败阈值的HTTP客户端
// 传入nil会创建一个常规的http.Client,也可以传入自定义的http.Client
client := circuit.NewHTTPClient(time.Second * 5, 10, nil)

// 使用包装后的客户端
resp, err := client.Get("http://example.com/resource.json")

以上示例展示了circuitbreaker库的主要功能,可以根据实际需求选择合适的熔断策略来保护你的远程调用。


更多关于golang实现服务熔断机制的Circuit Breaker插件库circuitbreaker的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang实现服务熔断机制的Circuit Breaker插件库circuitbreaker的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang 服务熔断机制:Circuit Breaker 使用指南

熔断器模式是微服务架构中重要的稳定性保障机制,可以有效防止服务雪崩效应。在 Go 生态中,circuitbreaker 是一个优秀的熔断器实现库。

安装 circuitbreaker

go get github.com/rubyist/circuitbreaker

基本使用示例

package main

import (
	"fmt"
	"time"
	"github.com/rubyist/circuitbreaker"
)

func main() {
	// 创建熔断器实例
	cb := circuit.NewThresholdBreaker(3) // 3次失败后熔断

	// 模拟服务调用
	for i := 0; i < 10; i++ {
		// 使用熔断器保护服务调用
		err := cb.Call(func() error {
			// 这里是实际的服务调用逻辑
			if i < 5 {
				return fmt.Errorf("模拟服务失败")
			}
			return nil
		}, 1*time.Second) // 设置超时时间

		if err != nil {
			fmt.Printf("调用失败: %v, 熔断状态: %v\n", err, cb.State())
		} else {
			fmt.Printf("调用成功, 熔断状态: %v\n", cb.State())
		}

		time.Sleep(500 * time.Millisecond)
	}
}

高级配置

func advancedExample() {
	// 创建可配置的熔断器
	cb := circuit.NewRateBreaker(0.5, 10) // 失败率50%以上触发,最少10次调用

	// 自定义配置
	cb = &circuit.Breaker{
		ShouldTrip: circuit.ThresholdTripFunc(5), // 5次失败后熔断
		WindowTime: 10 * time.Second,            // 统计窗口时间
		Timeout:    2 * time.Second,             // 超时时间
		ReadyToTrip: func(counts circuit.Counts) bool {
			// 自定义熔断触发条件
			return counts.ConsecFailures >= 3 || 
				(counts.Total >= 10 && counts.FailRate() >= 0.6)
		},
		OnStateChange: func(oldState, newState circuit.State) {
			// 状态变更回调
			fmt.Printf("状态变更: %s -> %s\n", oldState, newState)
		},
	}

	// 使用熔断器
	for i := 0; i < 15; i++ {
		err := cb.Call(func() error {
			if i%3 == 0 { // 模拟1/3的失败率
				return fmt.Errorf("服务错误")
			}
			return nil
		}, 0) // 0表示使用熔断器默认超时

		if err != nil {
			fmt.Printf("调用失败: %v, 状态: %v, 统计: %+v\n", 
				err, cb.State(), cb.Counts())
		} else {
			fmt.Printf("调用成功, 状态: %v\n", cb.State())
		}

		time.Sleep(300 * time.Millisecond)
	}
}

实际应用场景

package main

import (
	"context"
	"fmt"
	"net/http"
	"time"
	"github.com/rubyist/circuitbreaker"
)

var cb = circuit.NewThresholdBreaker(3)

func protectedAPICall(url string) (string, error) {
	var result string
	err := cb.Call(func() error {
		// 创建带超时的HTTP客户端
		client := &http.Client{
			Timeout: 2 * time.Second,
		}
		
		// 创建带超时的请求上下文
		ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
		defer cancel()
		
		req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
		if err != nil {
			return err
		}
		
		resp, err := client.Do(req)
		if err != nil {
			return err
		}
		defer resp.Body.Close()
		
		if resp.StatusCode != http.StatusOK {
			return fmt.Errorf("HTTP错误: %s", resp.Status)
		}
		
		// 处理响应...
		result = "处理后的响应数据"
		return nil
	}, 0) // 0表示使用熔断器默认超时

	return result, err
}

func main() {
	for i := 0; i < 10; i++ {
		res, err := protectedAPICall("https://example.com/api")
		if err != nil {
			fmt.Printf("API调用失败: %v (状态: %v)\n", err, cb.State())
		} else {
			fmt.Printf("API调用成功: %s (状态: %v)\n", res, cb.State())
		}
		
		time.Sleep(1 * time.Second)
	}
}

最佳实践

  1. 合理设置熔断阈值:根据服务特点设置失败次数或失败率阈值
  2. 监控熔断状态:通过 State() 方法监控熔断器状态变化
  3. 设置合理的超时时间:防止长时间阻塞
  4. 熔断恢复策略:熔断器会自动尝试半开状态恢复,但可以自定义恢复逻辑
  5. 结合重试机制:可以与重试机制配合使用,但要注意重试次数和熔断阈值的协调

总结

circuitbreaker 库提供了简单而强大的熔断器实现,通过合理配置可以显著提高系统的稳定性。在实际应用中,应该根据服务特点和业务需求调整熔断策略,并结合监控系统实时跟踪熔断状态。

回到顶部