跳到主要内容
版本: websocket_v1.x.x

断路器

断路器 是一种软件设计模式,用于防止服务在高故障率或慢响应时导致系统故障。通过阻止向不健康服务的请求,并在其稳定后允许恢复,它有助于提高系统弹性。

工作原理

  1. 关闭状态

    • 请求正常通过。
    • 故障会被计数。
    • 如果故障超过定义的阈值,电路将切换到打开状态。
  2. 打开状态

    • 请求会被立即阻止以防止过载。
    • 电路在进入半开状态前会保持打开一段超时时间
  3. 半开状态

    • 允许有限数量的请求来测试服务是否恢复。
    • 如果请求成功,电路会重置为关闭状态。
    • 如果请求失败,电路会返回到打开状态。

使用断路器的好处

防止微服务中的级联故障
✅ 通过避免重复的失败请求,提高系统可靠性
减轻负载过重的服务的压力并允许恢复。

安装

go get -u github.com/gofiber/fiber/v2
go get -u github.com/gofiber/contrib/circuitbreaker

签名

circuitbreaker.New(config ...circuitbreaker.Config) *circuitbreaker.Middleware 

配置

属性类型描述默认值
FailureThresholdint打开电路所需的连续错误次数5
Timeouttime.Duration断路器的超时时间10 * time.Second
SuccessThresholdint关闭电路所需的成功请求次数5
HalfOpenMaxConcurrentint半开状态下的最大并发请求数1
IsFailurefunc(error) bool用于确定错误是否为故障的自定义函数Status >= 500
OnOpenfunc(*fiber.Ctx)电路打开时的回调函数503 response
OnClosefunc(*fiber.Ctx)电路关闭时的回调函数继续请求
OnHalfOpenfunc(*fiber.Ctx)电路半开时的回调函数429 response

断路器在 Fiber 中的使用 (示例)

本指南解释了如何在 Fiber 应用中在不同级别使用断路器,从基本设置到高级自定义。

1. 基本设置

全局断路器保护所有路由。

示例:将断路器应用于所有路由

package main

import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/contrib/circuitbreaker"
)

func main() {
app := fiber.New()

// Create a new Circuit Breaker with custom configuration
cb := circuitbreaker.New(circuitbreaker.Config{
FailureThreshold: 3, // Max failures before opening the circuit
Timeout: 5 * time.Second, // Wait time before retrying
SuccessThreshold: 2, // Required successes to move back to closed state
})

// Apply Circuit Breaker to ALL routes
app.Use(circuitbreaker.Middleware(cb))

// Sample Route
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, world!")
})

// Optional: Expose health check endpoint
app.Get("/health/circuit", cb.HealthHandler())

// Optional: Expose metrics about the circuit breaker:
app.Get("/metrics/circuit", func(c *fiber.Ctx) error {
return c.JSON(cb.GetStateStats())
})

app.Listen(":3000")

// In your application shutdown logic
app.Shutdown(func() {
// Make sure to stop the circuit breaker when your application shuts down:
cb.Stop()
})
}

2. 针对特定路由和路由组的断路器

仅将断路器应用于特定路由。

app.Get("/protected", circuitbreaker.Middleware(cb), func(c *fiber.Ctx) error {
return c.SendString("Protected service running")
})

仅将断路器应用于特定路由组。

app := route.Group("/api")
app.Use(circuitbreaker.Middleware(cb))

// All routes in this group will be protected
app.Get("/users", getUsersHandler)
app.Post("/users", createUserHandler)

3. 带自定义故障处理的断路器

自定义电路打开时的响应。

cb := circuitbreaker.New(circuitbreaker.Config{
FailureThreshold: 3,
Timeout: 10 * time.Second,
OnOpen: func(c *fiber.Ctx) error {
return c.Status(fiber.StatusServiceUnavailable).
JSON(fiber.Map{"error": "Circuit Open: Service unavailable"})
},
OnHalfOpen: func(c *fiber.Ctx) error {
return c.Status(fiber.StatusTooManyRequests).
JSON(fiber.Map{"error": "Circuit Half-Open: Retrying service"})
},
OnClose: func(c *fiber.Ctx) error {
return c.Status(fiber.StatusOK).
JSON(fiber.Map{"message": "Circuit Closed: Service recovered"})
},
})

// Apply to a specific route
app.Get("/custom", circuitbreaker.Middleware(cb), func(c *fiber.Ctx) error {
return c.SendString("This service is protected by a Circuit Breaker")
})

✅ 现在,当故障超过阈值时,*将发送自定义错误响应

4. 用于外部 API 调用的断路器

在调用外部 API 时使用断路器


app.Get("/external-api", circuitbreaker.Middleware(cb), func(c *fiber.Ctx) error {
// Simulating an external API call
resp, err := fiber.Get("https://example.com/api")
if err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "External API failed")
}
return c.SendString(resp.Body())
})

✅ 如果外部 API 重复失败,断路器会阻止进一步的调用

5. 带并发请求处理的断路器

使用基于信号量的方法来限制并发请求

cb := circuitbreaker.New(circuitbreaker.Config{
FailureThreshold: 3,
Timeout: 5 * time.Second,
SuccessThreshold: 2,
HalfOpenSemaphore: make(chan struct{}, 2), // Allow only 2 concurrent requests
})

app.Get("/half-open-limit", circuitbreaker.Middleware(cb), func(c *fiber.Ctx) error {
time.Sleep(2 * time.Second) // Simulating slow response
return c.SendString("Half-Open: Limited concurrent requests")
})

✅ 当处于半开状态时,只允许 2 个并发请求

6. 带自定义指标的断路器

集成 Prometheus 指标结构化日志记录

cb := circuitbreaker.New(circuitbreaker.Config{
FailureThreshold: 5,
Timeout: 10 * time.Second,
OnOpen: func(c *fiber.Ctx) error {
log.Println("Circuit Breaker Opened!")
prometheus.Inc("circuit_breaker_open_count")
return c.Status(fiber.StatusServiceUnavailable).JSON(fiber.Map{"error": "Service Down"})
},
})

✅ 在电路打开时记录日志并增加 Prometheus 指标。

7. 高级:为不同服务使用多个断路器

为不同服务使用不同的断路器。


dbCB := circuitbreaker.New(circuitbreaker.Config{FailureThreshold: 5, Timeout: 10 * time.Second})
apiCB := circuitbreaker.New(circuitbreaker.Config{FailureThreshold: 3, Timeout: 5 * time.Second})

app.Get("/db-service", circuitbreaker.Middleware(dbCB), func(c *fiber.Ctx) error {
return c.SendString("DB service request")
})

app.Get("/api-service", circuitbreaker.Middleware(apiCB), func(c *fiber.Ctx) error {
return c.SendString("External API service request")
})

✅ 每个服务都有自己的故障阈值和超时时间。