fiber icon indicating copy to clipboard operation
fiber copied to clipboard

πŸ“ [Proposal]: Add Retry/CircuitBreaker Feature in proxy middleware

Open n9te9 opened this issue 1 year ago β€’ 6 comments

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

  • RFC 6585 (429 Too Many Requests): Enables clients to handle request rate limiting, providing guidance on when retries may be appropriate.
  • RFC 7231 (503 Service Unavailable): Indicates retry suggestions, especially when used with Retry-After headers for temporary server unavailability.

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:

  • [X] I agree to follow Fiber's Code of Conduct.
  • [X] I have searched for existing issues that describe my proposal before opening this one.
  • [X] I understand that a proposal that does not meet these guidelines may be closed without explanation.

n9te9 avatar Nov 07 '24 06:11 n9te9

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

welcome[bot] avatar Nov 07 '24 06:11 welcome[bot]

Related info:

  • https://failsafe-go.dev/circuit-breaker/
  • https://failsafe-go.dev/retry/

gaby avatar Nov 07 '24 13:11 gaby

@gaby I’d like to start working on the implementation for the Retry and Circuit Breaker features in the proxy middleware. I implement based-on failsafe-go configurable retry counts, backoff strategies, and circuit breaker conditions. Let me know if you have any guidance on the approach or if there are any specific considerations to keep in mind!

n9te9 avatar Nov 10 '24 06:11 n9te9

@lkeix I dont think we want to add failsafe-go to Fiber. We would just add the option for the user to implement their retry/sc mechanism.

gaby avatar Nov 10 '24 13:11 gaby

I believe we use the fasthttp client in the proxy. I wonder if it has some of these options built-in. Or if we could add them to our client and use that one instead.

gaby avatar Nov 10 '24 15:11 gaby

We have an addon for retry in Fiber codebase, which is also used by client -> https://github.com/gofiber/fiber/tree/main/addon/retry. I think we can use it and create new addon for circuit breaker

efectn avatar Dec 06 '24 12:12 efectn