gofiber / fiber

⚡️ Express inspired web framework written in Go
https://gofiber.io
MIT License
33.88k stars 1.66k forks source link

📝 [Proposal]: Add Retry/CircuitBreaker Feature in proxy middleware #3191

Open lkeix opened 18 hours ago

lkeix commented 18 hours ago

Feature Proposal Description

Background

It seems Fiber is often used in micro-service architecture, the concern is network convergence in micro-service architecture. The current Fiber proxy middleware lacks built-in retry and circuit breaker functionalities, which are essential for handling network failures and enhancing service reliability in microservice architectures. This proposal suggests adding RetryFunc and CircuitBreakerFunc fields in the proxy configuration to enable these patterns. Fiber proxy will enhance services availability by built-in Retry/CircuitBreaker functionalities.

Abstract/Details

Add Retry/CircuitBreaker feature in proxy middleware. This proposal involves adding two fields, RetryFunc and CircuitBreakerFunc, to the Config structure of Fiber’s proxy middleware. These fields will allow users to define custom retry and circuit breaker logic, giving them flexibility in handling network failures. Below is a diff showing the proposed changes to the Config structure.

type Config struct {
    // Next defines a function to skip this middleware when returned true.
    //
    // Optional. Default: nil
    Next func(c fiber.Ctx) bool

    // ModifyRequest allows you to alter the request
    //
    // Optional. Default: nil
    ModifyRequest fiber.Handler

    // ModifyResponse allows you to alter the response
    //
    // Optional. Default: nil
    ModifyResponse fiber.Handler

    // tls config for the http client.
    TlsConfig *tls.Config //nolint:stylecheck,revive // TODO: Rename to "TLSConfig" in v3

    // Client is custom client when client config is complex.
    // Note that Servers, Timeout, WriteBufferSize, ReadBufferSize, TlsConfig
    // and DialDualStack will not be used if the client are set.
    Client *fasthttp.LBClient

    // Servers defines a list of <scheme>://<host> HTTP servers,
    //
    // which are used in a round-robin manner.
    // i.e.: "https://foobar.com, http://www.foobar.com"
    //
    // Required
    Servers []string

    // Timeout is the request timeout used when calling the proxy client
    //
    // Optional. Default: 1 second
    Timeout time.Duration

    // Per-connection buffer size for requests' reading.
    // This also limits the maximum header size.
    // Increase this buffer if your clients send multi-KB RequestURIs
    // and/or multi-KB headers (for example, BIG cookies).
    ReadBufferSize int

    // Per-connection buffer size for responses' writing.
    WriteBufferSize int

    // Attempt to connect to both ipv4 and ipv6 host addresses if set to true.
    //
    // By default client connects only to ipv4 addresses, since unfortunately ipv6
    // remains broken in many networks worldwide :)
    //
    // Optional. Default: false
    DialDualStack bool

+       // RetryFunc can implement proxy retry function
+       // This property may be changed args/returns
+       //
+       // Optional. Default: nil
+       RetryFunc(fiber.Handler) error

+       // CircuitBreaker can implement proxy circuitbreaker function
+       // This property may be changed args/returns
+       //
+       // Optional. Default: nil
+       CircuitBreakerFunc func() error {}
}

func Do(...) {
  // wrap retry and circuitbreaker logic
  return doAction(c, addr, func(cli *fasthttp.Client, req *fasthttp.Request, resp *fasthttp.Response) error {
    // maybe changed this lines implementation
    // retry / circuitbreaker func is nil: same as existing logic
    return cli.Do(req, resp)
  }, clients...)
}

Alignment with Express API

N/a

HTTP RFC Standards Compliance

Maybe related

API Stability

This change has no effect. The added properties is set nil as default. Proxy middleware do existing logic, when the added properties is nil. This change completely maintain backward compatibility.

Feature Examples

When Fiber users want to implement retry/circuitbreaker in proxy, users can implement below.

func retry() {
  // implement retry logic
}

func circuitBreaker() {
  // implement circuit breaker logic
}

app.Use(proxy.Balancer(proxy.Config{
  RetryFunc: retryFunc,
  CircuitBreakerFunc: circuitBreaker
}))

Checklist:

welcome[bot] commented 18 hours ago

Thanks for opening your first issue here! 🎉 Be sure to follow the issue template! If you need help or want to chat with us, join us on Discord https://gofiber.io/discord

gaby commented 11 hours ago

Related info: