From 337f77a05aa0faf9ad9ce1c153868bfd8f1fb937 Mon Sep 17 00:00:00 2001 From: Erfan Momeni Date: Sat, 28 Dec 2024 23:56:08 +0330 Subject: [PATCH 01/12] feat: add load-shedding middleware with unit tests --- middleware/loadshedding/loadshedding.go | 40 +++++++++ middleware/loadshedding/loadshedding_test.go | 92 ++++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 middleware/loadshedding/loadshedding.go create mode 100644 middleware/loadshedding/loadshedding_test.go diff --git a/middleware/loadshedding/loadshedding.go b/middleware/loadshedding/loadshedding.go new file mode 100644 index 0000000000..156a31c66d --- /dev/null +++ b/middleware/loadshedding/loadshedding.go @@ -0,0 +1,40 @@ +package loadshedding + +import ( + "context" + "time" + + "github.com/gofiber/fiber/v3" +) + +// New creates a middleware handler enforces a timeout on request processing to manage server load. +// If a request exceeds the specified timeout, a custom load-shedding handler is executed. +func New(timeout time.Duration, loadSheddingHandler fiber.Handler, exclude func(fiber.Ctx) bool) fiber.Handler { + return func(c fiber.Ctx) error { + // Skip load-shedding for excluded requests + if exclude != nil && exclude(c) { + return c.Next() + } + + // Create a context with the specified timeout + ctx, cancel := context.WithTimeout(c.Context(), timeout) + defer cancel() + + // Channel to signal request completion + done := make(chan error, 1) + + // Process the handler in a separate goroutine + go func() { + done <- c.Next() + }() + + select { + case <-ctx.Done(): + // Timeout occurred; invoke the load-shedding handler + return loadSheddingHandler(c) + case err := <-done: + // Request completed successfully; return any handler error + return err + } + } +} diff --git a/middleware/loadshedding/loadshedding_test.go b/middleware/loadshedding/loadshedding_test.go new file mode 100644 index 0000000000..5651654ce2 --- /dev/null +++ b/middleware/loadshedding/loadshedding_test.go @@ -0,0 +1,92 @@ +package loadshedding_test + +import ( + "net/http/httptest" + "testing" + "time" + + "github.com/gofiber/fiber/v3" + "github.com/gofiber/fiber/v3/middleware/loadshedding" + "github.com/stretchr/testify/require" +) + +// Helper handlers +func successHandler(c fiber.Ctx) error { + return c.SendString("Request processed successfully!") +} + +func timeoutHandler(c fiber.Ctx) error { + time.Sleep(2 * time.Second) // Simulate a long-running request + return c.SendString("This should not appear") +} + +func loadSheddingHandler(c fiber.Ctx) error { + return c.Status(fiber.StatusServiceUnavailable).SendString("Service Overloaded") +} + +func excludedHandler(c fiber.Ctx) error { + return c.SendString("Excluded route") +} + +// go test -run Test_LoadSheddingExcluded +func Test_LoadSheddingExcluded(t *testing.T) { + t.Parallel() + app := fiber.New() + + // Middleware with exclusion + app.Use(loadshedding.New( + 1*time.Second, + loadSheddingHandler, + func(c fiber.Ctx) bool { return c.Path() == "/excluded" }, + )) + app.Get("/", successHandler) + app.Get("/excluded", excludedHandler) + + // Test excluded route + resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/excluded", nil)) + require.NoError(t, err) + require.Equal(t, fiber.StatusOK, resp.StatusCode) +} + +// go test -run Test_LoadSheddingTimeout +func Test_LoadSheddingTimeout(t *testing.T) { + t.Parallel() + app := fiber.New() + + // Middleware without exclusions + app.Use(loadshedding.New( + 1*time.Second, // Set timeout for the middleware + loadSheddingHandler, + nil, + )) + app.Get("/", timeoutHandler) + + // Create a custom HTTP client with a sufficient timeout + + // Test timeout behavior + req := httptest.NewRequest(fiber.MethodGet, "/", nil) + resp, err := app.Test(req, fiber.TestConfig{ + Timeout: 3 * time.Second, + }) + require.NoError(t, err) + require.Equal(t, fiber.StatusServiceUnavailable, resp.StatusCode) +} + +// go test -run Test_LoadSheddingSuccessfulRequest +func Test_LoadSheddingSuccessfulRequest(t *testing.T) { + t.Parallel() + app := fiber.New() + + // Middleware with sufficient time for request to complete + app.Use(loadshedding.New( + 2*time.Second, + loadSheddingHandler, + nil, + )) + app.Get("/", successHandler) + + // Test successful request + resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + require.NoError(t, err) + require.Equal(t, fiber.StatusOK, resp.StatusCode) +} From 3b385060ffee3094504862969a76f64c273042da Mon Sep 17 00:00:00 2001 From: Erfan Momeni Date: Sun, 29 Dec 2024 12:01:05 +0330 Subject: [PATCH 02/12] fix: update to avoid race condition --- middleware/loadshedding/loadshedding.go | 1 + 1 file changed, 1 insertion(+) diff --git a/middleware/loadshedding/loadshedding.go b/middleware/loadshedding/loadshedding.go index 156a31c66d..857b5e5def 100644 --- a/middleware/loadshedding/loadshedding.go +++ b/middleware/loadshedding/loadshedding.go @@ -25,6 +25,7 @@ func New(timeout time.Duration, loadSheddingHandler fiber.Handler, exclude func( // Process the handler in a separate goroutine go func() { + c.SetContext(ctx) done <- c.Next() }() From c8703bb16bad6dd7eff6670d7af4dab994d2dbcc Mon Sep 17 00:00:00 2001 From: Erfan Momeni Date: Sun, 29 Dec 2024 12:14:30 +0330 Subject: [PATCH 03/12] fix: update to avoid race condition --- middleware/loadshedding/loadshedding.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/middleware/loadshedding/loadshedding.go b/middleware/loadshedding/loadshedding.go index 857b5e5def..eb59040452 100644 --- a/middleware/loadshedding/loadshedding.go +++ b/middleware/loadshedding/loadshedding.go @@ -23,10 +23,14 @@ func New(timeout time.Duration, loadSheddingHandler fiber.Handler, exclude func( // Channel to signal request completion done := make(chan error, 1) + // Capture the current handler execution + handler := func() error { + return c.Next() + } + // Process the handler in a separate goroutine go func() { - c.SetContext(ctx) - done <- c.Next() + done <- handler() }() select { From 9f64a7b237eb0f3153dc9767e27ac2e8d230ef58 Mon Sep 17 00:00:00 2001 From: Erfan Momeni Date: Sun, 29 Dec 2024 12:42:18 +0330 Subject: [PATCH 04/12] fix: update to avoid race condition --- middleware/loadshedding/loadshedding.go | 28 ++++++++++---------- middleware/loadshedding/loadshedding_test.go | 16 ++++++----- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/middleware/loadshedding/loadshedding.go b/middleware/loadshedding/loadshedding.go index eb59040452..564c94bfe5 100644 --- a/middleware/loadshedding/loadshedding.go +++ b/middleware/loadshedding/loadshedding.go @@ -11,34 +11,34 @@ import ( // If a request exceeds the specified timeout, a custom load-shedding handler is executed. func New(timeout time.Duration, loadSheddingHandler fiber.Handler, exclude func(fiber.Ctx) bool) fiber.Handler { return func(c fiber.Ctx) error { - // Skip load-shedding for excluded requests + // Skip load-shedding logic for requests matching the exclusion criteria if exclude != nil && exclude(c) { return c.Next() } - // Create a context with the specified timeout + // Create a context with a timeout for the current request ctx, cancel := context.WithTimeout(c.Context(), timeout) defer cancel() - // Channel to signal request completion - done := make(chan error, 1) + // Set the new context with a timeout + c.SetContext(ctx) - // Capture the current handler execution - handler := func() error { - return c.Next() - } + // Process the request and capture any error + err := c.Next() + + // Create a channel to signal when request processing completes + done := make(chan error, 1) - // Process the handler in a separate goroutine + // Send the result of the request processing to the channel go func() { - done <- handler() + done <- err }() + // Handle either request completion or timeout select { - case <-ctx.Done(): - // Timeout occurred; invoke the load-shedding handler + case <-ctx.Done(): // Triggered if the timeout expires return loadSheddingHandler(c) - case err := <-done: - // Request completed successfully; return any handler error + case err := <-done: // Triggered if request processing completes return err } } diff --git a/middleware/loadshedding/loadshedding_test.go b/middleware/loadshedding/loadshedding_test.go index 5651654ce2..a91a67ec07 100644 --- a/middleware/loadshedding/loadshedding_test.go +++ b/middleware/loadshedding/loadshedding_test.go @@ -53,20 +53,24 @@ func Test_LoadSheddingTimeout(t *testing.T) { t.Parallel() app := fiber.New() - // Middleware without exclusions + // Middleware with a 1-second timeout app.Use(loadshedding.New( - 1*time.Second, // Set timeout for the middleware + 1*time.Second, // Middleware timeout loadSheddingHandler, nil, )) - app.Get("/", timeoutHandler) + app.Get("/", func(c fiber.Ctx) error { + // Simulate long-running request without creating goroutines + time.Sleep(2 * time.Second) + return c.SendString("This should not appear") + }) - // Create a custom HTTP client with a sufficient timeout + // Create a custom request + req := httptest.NewRequest(fiber.MethodGet, "/", nil) // Test timeout behavior - req := httptest.NewRequest(fiber.MethodGet, "/", nil) resp, err := app.Test(req, fiber.TestConfig{ - Timeout: 3 * time.Second, + Timeout: 3 * time.Second, // Ensure the test timeout exceeds middleware timeout }) require.NoError(t, err) require.Equal(t, fiber.StatusServiceUnavailable, resp.StatusCode) From bd4dc0c02f84e57f5f36b6d6715522ec92707ad2 Mon Sep 17 00:00:00 2001 From: Erfan Momeni Date: Mon, 30 Dec 2024 02:19:59 +0330 Subject: [PATCH 05/12] chore: update --- middleware/loadshedding/loadshedding_test.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/middleware/loadshedding/loadshedding_test.go b/middleware/loadshedding/loadshedding_test.go index a91a67ec07..b3e9d3dc2a 100644 --- a/middleware/loadshedding/loadshedding_test.go +++ b/middleware/loadshedding/loadshedding_test.go @@ -59,11 +59,7 @@ func Test_LoadSheddingTimeout(t *testing.T) { loadSheddingHandler, nil, )) - app.Get("/", func(c fiber.Ctx) error { - // Simulate long-running request without creating goroutines - time.Sleep(2 * time.Second) - return c.SendString("This should not appear") - }) + app.Get("/", timeoutHandler) // Create a custom request req := httptest.NewRequest(fiber.MethodGet, "/", nil) From 6287ea1d845c0f1c69305e251e40b6c1734c209c Mon Sep 17 00:00:00 2001 From: Erfan Momeni Date: Thu, 2 Jan 2025 23:10:53 +0330 Subject: [PATCH 06/12] docs: add loadshedding middleware to what's new document --- docs/whats_new.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/docs/whats_new.md b/docs/whats_new.md index 321df424d6..e4aa275ff6 100644 --- a/docs/whats_new.md +++ b/docs/whats_new.md @@ -31,6 +31,7 @@ Here's a quick overview of the changes in Fiber `v3`: - [Filesystem](#filesystem) - [Monitor](#monitor) - [Healthcheck](#healthcheck) + - [Load shedding](#loadshedding) - [📋 Migration guide](#-migration-guide) ## Drop for old Go versions @@ -810,6 +811,15 @@ The Healthcheck middleware has been enhanced to support more than two routes, wi Refer to the [healthcheck middleware migration guide](./middleware/healthcheck.md) or the [general migration guide](#-migration-guide) to review the changes. +### Load shedding +We've added **Load Shedding Middleware**.It ensures system stability under high load by enforcing timeouts on request processing. This mechanism allows the application to shed excessive load gracefully and maintain responsiveness. + +**Functionality** +- **Timeout Enforcement**: Automatically terminates requests exceeding a specified processing time. +- **Custom Response**: Uses a configurable load-shedding handler to define the response for shed requests. +- **Request Exclusion**: Allows certain requests to bypass load-shedding logic through an exclusion filter. + +This middleware is designed to enhance server resilience and improve the user experience during periods of high traffic. ## 📋 Migration guide - [🚀 App](#-app-1) @@ -1361,6 +1371,34 @@ app.Get(healthcheck.DefaultStartupEndpoint, healthcheck.NewHealthChecker(healthc app.Get("/live", healthcheck.NewHealthChecker()) ``` +#### Load shedding +This middleware uses `context.WithTimeout` to manage the lifecycle of requests. If a request exceeds the specified timeout, the custom load-shedding handler is triggered, ensuring the system remains stable under stress. + +**Key Parameters** + +`timeout` (`time.Duration`): The maximum time a request is allowed to process. Requests exceeding this time are terminated. + +`loadSheddingHandler` (`fiber.Handler`): A custom handler that executes when a request exceeds the timeout. Typically used to return a `503 Service Unavailable` response or a custom message. + +`exclude` (`func(fiber.Ctx) bool`): A filter function to exclude specific requests from being subjected to the load-shedding logic (optional). + +**Usage Example** + +```go +import "github.com/gofiber/fiber/v3/middleware/loadshedding + +app.Use(loadshedding.New( + 10*time.Second, // Timeout duration + func(c fiber.Ctx) error { // Load shedding response + return c.Status(fiber.StatusServiceUnavailable). + SendString("Service overloaded, try again later.") + }, + func(c fiber.Ctx) bool { // Exclude health checks + return c.Path() == "/health" + }, +)) +``` + #### Monitor Since v3 the Monitor middleware has been moved to the [Contrib package](https://github.com/gofiber/contrib/tree/main/monitor) From f4682bd976ca9fbf0fbfc9fcedaf50a1a9f2c224 Mon Sep 17 00:00:00 2001 From: Erfan Momeni Date: Fri, 3 Jan 2025 19:29:00 +0330 Subject: [PATCH 07/12] docs: add loadshedding middleware --- .github/README.md | 1 + docs/middleware/loadshedding.md | 73 +++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 docs/middleware/loadshedding.md diff --git a/.github/README.md b/.github/README.md index cb7b19b376..5a20c5a535 100644 --- a/.github/README.md +++ b/.github/README.md @@ -688,6 +688,7 @@ Here is a list of middleware that are included within the Fiber framework. | [idempotency](https://github.com/gofiber/fiber/tree/main/middleware/idempotency) | Allows for fault-tolerant APIs where duplicate requests do not erroneously cause the same action performed multiple times on the server-side. | | [keyauth](https://github.com/gofiber/fiber/tree/main/middleware/keyauth) | Adds support for key based authentication. | | [limiter](https://github.com/gofiber/fiber/tree/main/middleware/limiter) | Adds Rate-limiting support to Fiber. Use to limit repeated requests to public APIs and/or endpoints such as password reset. | +| [loadshedding](https://github.com/gofiber/fiber/tree/main/middleware/loadshedding) | Gracefully manages server load by enforcing request timeouts and handling resource-intensive requests during high-traffic periods. | | [logger](https://github.com/gofiber/fiber/tree/main/middleware/logger) | HTTP request/response logger. | | [pprof](https://github.com/gofiber/fiber/tree/main/middleware/pprof) | Serves runtime profiling data in pprof format. | | [proxy](https://github.com/gofiber/fiber/tree/main/middleware/proxy) | Allows you to proxy requests to multiple servers. | diff --git a/docs/middleware/loadshedding.md b/docs/middleware/loadshedding.md new file mode 100644 index 0000000000..c98c242185 --- /dev/null +++ b/docs/middleware/loadshedding.md @@ -0,0 +1,73 @@ +--- +id: loadshedding +--- + +# Load Shedding + +Load Shedding middleware for [Fiber](https://github.com/gofiber/fiber) is designed to enhance server stability by +enforcing timeouts on request processing. It helps manage server load effectively by gracefully handling requests that +exceed a specified timeout duration. This is especially useful in high-traffic scenarios, where preventing server +overload is critical to maintaining service availability and performance. + +### Features + +- **Request Timeout Enforcement**: Ensures that no request exceeds the specified processing time. +- **Customizable Response**: Allows you to define a specific response for timed-out requests. +- **Exclusion Criteria**: Provides flexibility to exclude specific requests from load-shedding logic. +- **Improved Stability**: Helps prevent server crashes under heavy load by shedding excess requests. + +### Use Cases + +- **High-Traffic Scenarios**: Protect critical resources by shedding long-running or resource-intensive requests. +- **Health Check Protection**: Exclude endpoints like `/health` to ensure critical monitoring remains unaffected. +- **Dynamic Load Management**: Use exclusion logic to prioritize or deprioritize requests dynamically. + +--- + +## Signature + +```go +func New(timeout time.Duration, loadSheddingHandler fiber.Handler, exclude func (fiber.Ctx) bool) fiber.Handler +``` + +## Config + +| Property | Type | Description | Default | +|:----------------------|:------------------------------------|:-----------------------------------------------------------------------------------------------|:---------| +| `timeout` | `time.Duration` | Maximum allowed processing time for a request. | Required | +| `loadSheddingHandler` | `fiber.Handler` | Handler invoked for requests that exceed the timeout. | Required | +| `exclude` | `func(fiber.Ctx) bool` | Optional function to exclude specific requests from load-shedding logic. | `nil` | + +## Example Usage +Import the middleware package and integrate it into your Fiber application: + +```go +import ( + "time" + "github.com/gofiber/fiber/v3" + "github.com/gofiber/fiber/v3/middleware/loadshedding" +) + +func main() { + app := fiber.New() + + // Basic usage with a 5-second timeout + app.Use(loadshedding.New(5*time.Second, func(c fiber.Ctx) error { + return c.Status(fiber.StatusServiceUnavailable).SendString("Service unavailable due to high load") + }, nil)) + + // Advanced usage with exclusion logic for specific endpoints + app.Use(loadshedding.New(3*time.Second, func(c fiber.Ctx) error { + return c.Status(fiber.StatusServiceUnavailable).SendString("Request timed out") + }, func(c fiber.Ctx) bool { + return c.Path() == "/health" + })) + + app.Get("/", func(c fiber.Ctx) error { + time.Sleep(4 * time.Second) // Simulating a long-running request + return c.SendString("Hello, world!") + }) + + app.Listen(":3000") +} +``` \ No newline at end of file From a47694516f5dc250bd9749eeaa49b1d10cb8a834 Mon Sep 17 00:00:00 2001 From: Erfan Momeni Date: Sat, 4 Jan 2025 10:43:23 +0330 Subject: [PATCH 08/12] docs: fix lint errors --- docs/middleware/loadshedding.md | 6 +++--- docs/whats_new.md | 14 ++++++++++---- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/docs/middleware/loadshedding.md b/docs/middleware/loadshedding.md index c98c242185..927bc8ba95 100644 --- a/docs/middleware/loadshedding.md +++ b/docs/middleware/loadshedding.md @@ -9,14 +9,14 @@ enforcing timeouts on request processing. It helps manage server load effectivel exceed a specified timeout duration. This is especially useful in high-traffic scenarios, where preventing server overload is critical to maintaining service availability and performance. -### Features +## Features - **Request Timeout Enforcement**: Ensures that no request exceeds the specified processing time. - **Customizable Response**: Allows you to define a specific response for timed-out requests. - **Exclusion Criteria**: Provides flexibility to exclude specific requests from load-shedding logic. - **Improved Stability**: Helps prevent server crashes under heavy load by shedding excess requests. -### Use Cases +## Use Cases - **High-Traffic Scenarios**: Protect critical resources by shedding long-running or resource-intensive requests. - **Health Check Protection**: Exclude endpoints like `/health` to ensure critical monitoring remains unaffected. @@ -70,4 +70,4 @@ func main() { app.Listen(":3000") } -``` \ No newline at end of file +``` diff --git a/docs/whats_new.md b/docs/whats_new.md index e4aa275ff6..43c44994dd 100644 --- a/docs/whats_new.md +++ b/docs/whats_new.md @@ -31,7 +31,7 @@ Here's a quick overview of the changes in Fiber `v3`: - [Filesystem](#filesystem) - [Monitor](#monitor) - [Healthcheck](#healthcheck) - - [Load shedding](#loadshedding) + - [Load shedding](#-load-shedding) - [📋 Migration guide](#-migration-guide) ## Drop for old Go versions @@ -812,14 +812,19 @@ The Healthcheck middleware has been enhanced to support more than two routes, wi Refer to the [healthcheck middleware migration guide](./middleware/healthcheck.md) or the [general migration guide](#-migration-guide) to review the changes. ### Load shedding + We've added **Load Shedding Middleware**.It ensures system stability under high load by enforcing timeouts on request processing. This mechanism allows the application to shed excessive load gracefully and maintain responsiveness. -**Functionality** +#### Functionality + - **Timeout Enforcement**: Automatically terminates requests exceeding a specified processing time. + - **Custom Response**: Uses a configurable load-shedding handler to define the response for shed requests. + - **Request Exclusion**: Allows certain requests to bypass load-shedding logic through an exclusion filter. This middleware is designed to enhance server resilience and improve the user experience during periods of high traffic. + ## 📋 Migration guide - [🚀 App](#-app-1) @@ -1372,9 +1377,10 @@ app.Get("/live", healthcheck.NewHealthChecker()) ``` #### Load shedding + This middleware uses `context.WithTimeout` to manage the lifecycle of requests. If a request exceeds the specified timeout, the custom load-shedding handler is triggered, ensuring the system remains stable under stress. -**Key Parameters** +##### Key Parameters `timeout` (`time.Duration`): The maximum time a request is allowed to process. Requests exceeding this time are terminated. @@ -1382,7 +1388,7 @@ This middleware uses `context.WithTimeout` to manage the lifecycle of requests. `exclude` (`func(fiber.Ctx) bool`): A filter function to exclude specific requests from being subjected to the load-shedding logic (optional). -**Usage Example** +#### Usage Example ```go import "github.com/gofiber/fiber/v3/middleware/loadshedding From beb5896e0551d18b6903c8b33771c0b33180465a Mon Sep 17 00:00:00 2001 From: Erfan Momeni Date: Sat, 4 Jan 2025 10:44:24 +0330 Subject: [PATCH 09/12] docs: fix lint errors --- docs/whats_new.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/whats_new.md b/docs/whats_new.md index 43c44994dd..604c0ae6aa 100644 --- a/docs/whats_new.md +++ b/docs/whats_new.md @@ -31,7 +31,7 @@ Here's a quick overview of the changes in Fiber `v3`: - [Filesystem](#filesystem) - [Monitor](#monitor) - [Healthcheck](#healthcheck) - - [Load shedding](#-load-shedding) + - [Load shedding](#load-shedding) - [📋 Migration guide](#-migration-guide) ## Drop for old Go versions From 0fd8df704d7445c07dead245b77d8dc5081873aa Mon Sep 17 00:00:00 2001 From: Erfan Momeni Date: Sat, 4 Jan 2025 10:45:48 +0330 Subject: [PATCH 10/12] docs: fix lint errors --- docs/whats_new.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/whats_new.md b/docs/whats_new.md index 604c0ae6aa..b4544f753f 100644 --- a/docs/whats_new.md +++ b/docs/whats_new.md @@ -1388,7 +1388,7 @@ This middleware uses `context.WithTimeout` to manage the lifecycle of requests. `exclude` (`func(fiber.Ctx) bool`): A filter function to exclude specific requests from being subjected to the load-shedding logic (optional). -#### Usage Example +##### Usage Example ```go import "github.com/gofiber/fiber/v3/middleware/loadshedding From a192bd126d91e6fea644650b88013404a33463a5 Mon Sep 17 00:00:00 2001 From: Erfan Momeni Date: Sun, 5 Jan 2025 03:00:45 +0330 Subject: [PATCH 11/12] fix: update --- docs/middleware/loadshedding.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/middleware/loadshedding.md b/docs/middleware/loadshedding.md index 927bc8ba95..048373b5d5 100644 --- a/docs/middleware/loadshedding.md +++ b/docs/middleware/loadshedding.md @@ -39,6 +39,7 @@ func New(timeout time.Duration, loadSheddingHandler fiber.Handler, exclude func | `exclude` | `func(fiber.Ctx) bool` | Optional function to exclude specific requests from load-shedding logic. | `nil` | ## Example Usage + Import the middleware package and integrate it into your Fiber application: ```go From 4c8a17e3db4ef48c0dae00d1d3b4e0d6a2399d89 Mon Sep 17 00:00:00 2001 From: Juan Calderon-Perez <835733+gaby@users.noreply.github.com> Date: Sat, 4 Jan 2025 20:34:16 -0500 Subject: [PATCH 12/12] Update docs --- docs/middleware/loadshedding.md | 65 ++++++++++++++++++--------------- docs/whats_new.md | 14 +++---- 2 files changed, 42 insertions(+), 37 deletions(-) diff --git a/docs/middleware/loadshedding.md b/docs/middleware/loadshedding.md index 048373b5d5..646c9b67ca 100644 --- a/docs/middleware/loadshedding.md +++ b/docs/middleware/loadshedding.md @@ -4,43 +4,40 @@ id: loadshedding # Load Shedding -Load Shedding middleware for [Fiber](https://github.com/gofiber/fiber) is designed to enhance server stability by -enforcing timeouts on request processing. It helps manage server load effectively by gracefully handling requests that -exceed a specified timeout duration. This is especially useful in high-traffic scenarios, where preventing server -overload is critical to maintaining service availability and performance. +The **Load Shedding** middleware for [Fiber](https://github.com/gofiber/fiber) helps maintain server stability by applying request-processing timeouts. It prevents resource exhaustion by gracefully rejecting requests that exceed a specified time limit. This is particularly beneficial in high-traffic scenarios, where preventing overload is crucial to sustaining service availability and performance. ## Features -- **Request Timeout Enforcement**: Ensures that no request exceeds the specified processing time. -- **Customizable Response**: Allows you to define a specific response for timed-out requests. -- **Exclusion Criteria**: Provides flexibility to exclude specific requests from load-shedding logic. -- **Improved Stability**: Helps prevent server crashes under heavy load by shedding excess requests. +- **Request Timeout Enforcement**: Automatically terminates any request that exceeds the configured processing time. +- **Customizable Response**: Enables you to define a specialized response for timed-out requests. +- **Exclusion Logic**: Lets you skip load-shedding for specific requests, such as health checks or other critical endpoints. +- **Enhanced Stability**: Helps avoid server crashes or sluggish performance under heavy load by shedding excess requests. ## Use Cases -- **High-Traffic Scenarios**: Protect critical resources by shedding long-running or resource-intensive requests. -- **Health Check Protection**: Exclude endpoints like `/health` to ensure critical monitoring remains unaffected. -- **Dynamic Load Management**: Use exclusion logic to prioritize or deprioritize requests dynamically. +- **High-Traffic Scenarios**: Safeguard critical resources by rejecting overly long or resource-intensive requests. +- **Health Check Protection**: Exclude monitoring endpoints (e.g., `/health`) to ensure uninterrupted external checks. +- **Dynamic Load Management**: Utilize exclusion logic to adjust load-shedding behavior for specific routes or request types. --- ## Signature ```go -func New(timeout time.Duration, loadSheddingHandler fiber.Handler, exclude func (fiber.Ctx) bool) fiber.Handler +func New(timeout time.Duration, loadSheddingHandler fiber.Handler, exclude func(fiber.Ctx) bool) fiber.Handler ``` ## Config -| Property | Type | Description | Default | -|:----------------------|:------------------------------------|:-----------------------------------------------------------------------------------------------|:---------| -| `timeout` | `time.Duration` | Maximum allowed processing time for a request. | Required | -| `loadSheddingHandler` | `fiber.Handler` | Handler invoked for requests that exceed the timeout. | Required | -| `exclude` | `func(fiber.Ctx) bool` | Optional function to exclude specific requests from load-shedding logic. | `nil` | +| Property | Type | Description | Default | +|-----------------------|--------------------|----------------------------------------------------------------------------------|-----------| +| `timeout` | `time.Duration` | The maximum allowed processing time for a request. | Required | +| `loadSheddingHandler`| `fiber.Handler` | The handler invoked for requests that exceed the `timeout`. | Required | +| `exclude` | `func(fiber.Ctx) bool` | Optional function to exclude certain requests from load-shedding logic. | `nil` | ## Example Usage -Import the middleware package and integrate it into your Fiber application: +Import the middleware and configure it within your Fiber application: ```go import ( @@ -53,19 +50,29 @@ func main() { app := fiber.New() // Basic usage with a 5-second timeout - app.Use(loadshedding.New(5*time.Second, func(c fiber.Ctx) error { - return c.Status(fiber.StatusServiceUnavailable).SendString("Service unavailable due to high load") - }, nil)) - - // Advanced usage with exclusion logic for specific endpoints - app.Use(loadshedding.New(3*time.Second, func(c fiber.Ctx) error { - return c.Status(fiber.StatusServiceUnavailable).SendString("Request timed out") - }, func(c fiber.Ctx) bool { - return c.Path() == "/health" - })) + app.Use(loadshedding.New( + 5*time.Second, + func(c fiber.Ctx) error { + return c.Status(fiber.StatusServiceUnavailable).SendString("Service unavailable due to high load") + }, + nil, + )) + + // Advanced usage with an exclusion function for specific endpoints + app.Use(loadshedding.New( + 3*time.Second, + func(c fiber.Ctx) error { + return c.Status(fiber.StatusServiceUnavailable).SendString("Request timed out") + }, + func(c fiber.Ctx) bool { + // Exclude /health from load-shedding + return c.Path() == "/health" + }, + )) app.Get("/", func(c fiber.Ctx) error { - time.Sleep(4 * time.Second) // Simulating a long-running request + // Simulating a long-running request + time.Sleep(4 * time.Second) return c.SendString("Hello, world!") }) diff --git a/docs/whats_new.md b/docs/whats_new.md index b4544f753f..e786bf0bd7 100644 --- a/docs/whats_new.md +++ b/docs/whats_new.md @@ -811,19 +811,17 @@ The Healthcheck middleware has been enhanced to support more than two routes, wi Refer to the [healthcheck middleware migration guide](./middleware/healthcheck.md) or the [general migration guide](#-migration-guide) to review the changes. -### Load shedding +### Load Shedding -We've added **Load Shedding Middleware**.It ensures system stability under high load by enforcing timeouts on request processing. This mechanism allows the application to shed excessive load gracefully and maintain responsiveness. +We’ve introduced the **Load Shedding Middleware** to keep your system stable under heavy load. It automatically terminates requests that exceed a specified processing time, enabling the application to gracefully shed excessive load while maintaining responsiveness. #### Functionality -- **Timeout Enforcement**: Automatically terminates requests exceeding a specified processing time. +- **Timeout Enforcement**: Automatically terminates requests that exceed the defined maximum processing time. +- **Customizable Response**: Supports a configurable load-shedding handler to define the response for timed-out requests. +- **Exclusion Logic**: Allows certain requests or routes to bypass the load-shedding mechanism based on defined rules. -- **Custom Response**: Uses a configurable load-shedding handler to define the response for shed requests. - -- **Request Exclusion**: Allows certain requests to bypass load-shedding logic through an exclusion filter. - -This middleware is designed to enhance server resilience and improve the user experience during periods of high traffic. +By applying timeouts and shedding excess load, this middleware helps your server remain resilient and ensures a smoother user experience during high-traffic periods. ## 📋 Migration guide