Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
3 tasks done
lkeix opened this issue Nov 7, 2024 · 5 comments
Open
3 tasks done

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

lkeix opened this issue Nov 7, 2024 · 5 comments

Comments

@lkeix
Copy link

lkeix commented Nov 7, 2024

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:

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

welcome bot commented Nov 7, 2024

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
Copy link
Member

gaby commented Nov 7, 2024

Related info:

@lkeix
Copy link
Author

lkeix commented Nov 10, 2024

@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!

@gaby
Copy link
Member

gaby commented Nov 10, 2024

@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
Copy link
Member

gaby commented Nov 10, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants