From dd24a29f8091964040066631f388ed511b62fd2c Mon Sep 17 00:00:00 2001 From: Doksanbir Date: Sun, 13 Sep 2026 09:29:24 +0300 Subject: [PATCH] feat: add Microservices Load Shedding pattern (#3229) (#3599) * feat: add Microservices Load Shedding pattern (#3229) * fix: harden load shedder release and report the admitted count release() clamps the in-flight count at zero, acquire() returns the admitted count that the service logs, and the demo summary reports the total shed. The class diagram is a rendered PNG. --- microservices-load-shedding/README.md | 237 ++++++++++++++++++ .../etc/microservices-load-shedding.urm.png | Bin 0 -> 158059 bytes .../etc/microservices-load-shedding.urm.puml | 90 +++++++ microservices-load-shedding/pom.xml | 70 ++++++ .../java/com/iluwatar/loadshedding/App.java | 194 ++++++++++++++ .../loadshedding/LoadShedException.java | 57 +++++ .../iluwatar/loadshedding/LoadShedder.java | 146 +++++++++++ .../com/iluwatar/loadshedding/Priority.java | 39 +++ .../com/iluwatar/loadshedding/Request.java | 36 +++ .../iluwatar/loadshedding/RequestHandler.java | 41 +++ .../com/iluwatar/loadshedding/Response.java | 55 ++++ .../loadshedding/ShedGuardedService.java | 84 +++++++ .../com/iluwatar/loadshedding/AppTest.java | 177 +++++++++++++ .../loadshedding/LoadShedderTest.java | 201 +++++++++++++++ .../loadshedding/ShedGuardedServiceTest.java | 80 ++++++ pom.xml | 1 + 16 files changed, 1508 insertions(+) create mode 100644 microservices-load-shedding/README.md create mode 100644 microservices-load-shedding/etc/microservices-load-shedding.urm.png create mode 100644 microservices-load-shedding/etc/microservices-load-shedding.urm.puml create mode 100644 microservices-load-shedding/pom.xml create mode 100644 microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/App.java create mode 100644 microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/LoadShedException.java create mode 100644 microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/LoadShedder.java create mode 100644 microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/Priority.java create mode 100644 microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/Request.java create mode 100644 microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/RequestHandler.java create mode 100644 microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/Response.java create mode 100644 microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/ShedGuardedService.java create mode 100644 microservices-load-shedding/src/test/java/com/iluwatar/loadshedding/AppTest.java create mode 100644 microservices-load-shedding/src/test/java/com/iluwatar/loadshedding/LoadShedderTest.java create mode 100644 microservices-load-shedding/src/test/java/com/iluwatar/loadshedding/ShedGuardedServiceTest.java diff --git a/microservices-load-shedding/README.md b/microservices-load-shedding/README.md new file mode 100644 index 000000000..ae2ef09e1 --- /dev/null +++ b/microservices-load-shedding/README.md @@ -0,0 +1,237 @@ +--- +title: "Load Shedding Pattern in Java: Protecting Microservices from Overload" +shortTitle: Load Shedding +description: "Learn the Load Shedding pattern in Java: reject excess requests at the door, keep critical traffic flowing and stop overload from turning into an outage. Includes a runnable example, class diagram and trade-offs." +category: Resilience +language: en +tag: + - Fault tolerance + - Microservices + - Performance + - Resource management + - Scalability +--- + +## Also known as + +* Overload protection +* Admission control +* Graceful degradation under load + +## Intent of Load Shedding Design Pattern + +Keep a service responsive when it receives more work than it can handle by measuring its own load and rejecting excess requests immediately, before they consume threads, memory or connections. The requests that are accepted are served with normal latency, the rest fail fast so callers can retry or degrade gracefully. + +## Detailed Explanation of Load Shedding Pattern with Real-World Examples + +Real-world example + +> A power grid that is asked for more electricity than it can generate does not try to serve everybody a little worse. It disconnects selected neighbourhoods in a controlled way, keeps hospitals and traffic lights powered, and reconnects the rest when generation catches up. Without this deliberate "load shedding" the frequency would drop and the whole grid would collapse. + +In plain words + +> When a service is at capacity, say no to new requests right away instead of letting them queue up and slow everything down. Drop the least important work first. + +Google's Site Reliability Engineering book says + +> A server that is overloaded should degrade gracefully... it is better to reject some requests quickly than to accept all of them and serve every request slowly or not at all. + +Flowchart + +```mermaid +flowchart TD + A[Incoming request] --> B{In-flight below limit
for this priority?} + B -- yes --> C[Admit: in-flight + 1] + C --> D[Process request] + D --> E[Release: in-flight - 1] + E --> F[ACCEPTED response] + B -- no --> G[Count as shed] + G --> H[REJECTED response
fail fast, retry later] +``` + +![Load Shedding class diagram](./etc/microservices-load-shedding.urm.png) + +## Programmatic Example of Load Shedding Pattern in Java + +Our example is an order service that can process five requests at the same time. When a slow payment provider makes orders pile up inside the service, new requests are shed according to their priority: best-effort work is dropped first, regular traffic is dropped when the service is almost full, and one slot is always kept free for critical requests such as checkout. + +Every request carries a `Priority`. It is the only piece of information the shedder needs. + +```java +public enum Priority { + CRITICAL, + NORMAL, + LOW +} + +public record Request(String id, Priority priority, String description) {} +``` + +The `LoadShedder` is the admission controller. It knows the hard capacity of the service and a limit per priority: low priority requests are shed early, normal requests may not touch the reserve kept for critical ones, and critical requests may use the whole capacity. The admission check is lock-free: the in-flight count is updated with an atomic accumulator whose function refuses to increment past the limit, so concurrent callers can never push the in-flight count above the capacity. A request that cannot be admitted gets a `LoadShedException` immediately instead of a place in a queue. + +```java +public class LoadShedder { + + private final int maxInFlight; + private final Map limits = new EnumMap<>(Priority.class); + private final AtomicInteger inFlight = new AtomicInteger(); + private final LongAdder accepted = new LongAdder(); + private final Map shed = new EnumMap<>(Priority.class); + + public LoadShedder(int maxInFlight, int lowPriorityLimit, int criticalReserve) { + // validation omitted + this.maxInFlight = maxInFlight; + limits.put(Priority.CRITICAL, maxInFlight); + limits.put(Priority.NORMAL, maxInFlight - criticalReserve); + limits.put(Priority.LOW, lowPriorityLimit); + for (var priority : Priority.values()) { + shed.put(priority, new LongAdder()); + } + } + + public int acquire(Request request) { + var priority = request.priority(); + var limit = limits.get(priority); + // The accumulator is a pure function, so it is safe for the atomic to re-apply it under + // contention: the count is only incremented while it is below the limit for this priority. + var previous = + inFlight.getAndAccumulate( + 1, (current, increment) -> current >= limit ? current : current + increment); + if (previous >= limit) { + // Fail fast: the caller gets an immediate rejection instead of waiting in a queue. + shed.get(priority).increment(); + throw new LoadShedException(request, previous, limit); + } + accepted.increment(); + return previous + 1; + } + + public void release() { + // Clamped at zero so that an unmatched release cannot hand out capacity the service lacks. + inFlight.updateAndGet(current -> Math.max(0, current - 1)); + } +} +``` + +`ShedGuardedService` puts the shedder in front of the real business logic, which is a plain `RequestHandler` function. Shed requests are answered with a `REJECTED` response right away and never reach the handler. Admitted requests always release their slot when they finish, even when the handler throws. + +```java +@Slf4j +public class ShedGuardedService { + + private final String name; + private final LoadShedder shedder; + private final RequestHandler handler; + + public Response handle(Request request) { + int inFlight; + try { + // The count is taken from the admission itself: reading it back afterwards could report a + // value that belongs to a concurrent request. + inFlight = shedder.acquire(request); + } catch (LoadShedException e) { + LOGGER.warn("[{}] shed {} ({}): {}", name, request.id(), request.priority(), e.getMessage()); + return Response.rejected(request, e.getMessage()); + } + LOGGER.info("[{}] admitted {} ({}), {}/{} in flight", name, request.id(), request.priority(), + inFlight, shedder.getMaxInFlight()); + try { + return Response.accepted(request, handler.handle(request)); + } finally { + shedder.release(); + } + } +} +``` + +The `App` drives three phases. Under light load every request is admitted. Then the payment provider becomes slow, four orders get stuck inside the service and three probes are sent: the low priority one is shed because the service is past the low priority limit, the normal one is shed because only the critical reserve is left, and the critical checkout is admitted into that reserve. When the provider recovers the stuck orders complete and new requests are admitted again. + +```java +var shedder = new LoadShedder(CAPACITY, LOW_PRIORITY_LIMIT, CRITICAL_RESERVE); +var orderService = new ShedGuardedService("order-service", shedder, paymentProvider); + +// Phase 2: four orders are stuck behind a slow payment provider +report(orderService.handle(new Request("p1", Priority.LOW, "prefetch recommendations"))); +report(orderService.handle(new Request("p2", Priority.NORMAL, "view cart"))); +var checkout = executor.submit( + () -> orderService.handle(new Request("p3", Priority.CRITICAL, "checkout payment"))); +``` + +Running the program produces output similar to this: + +``` +Order service capacity: 5 in flight, low priority shed at 3, 1 slot reserved for critical requests +--- Phase 1: light load, every request is admitted --- +[order-service] admitted r1 (LOW), 1/5 in flight +r1 -> ACCEPTED: processed prefetch recommendations +[order-service] admitted r2 (NORMAL), 1/5 in flight +r2 -> ACCEPTED: processed view cart +--- Phase 2: payment provider slows down, orders pile up --- +[order-service] admitted order-1 (NORMAL), 1/5 in flight +[order-service] admitted order-2 (NORMAL), 2/5 in flight +[order-service] admitted order-3 (NORMAL), 3/5 in flight +[order-service] admitted order-4 (NORMAL), 4/5 in flight +4 of 5 slots busy, probing with every priority +[order-service] shed p1 (LOW): Request p1 shed: 4 requests in flight, limit for LOW priority is 3 +p1 -> REJECTED: Request p1 shed: 4 requests in flight, limit for LOW priority is 3 +[order-service] shed p2 (NORMAL): Request p2 shed: 4 requests in flight, limit for NORMAL priority is 4 +p2 -> REJECTED: Request p2 shed: 4 requests in flight, limit for NORMAL priority is 4 +[order-service] admitted p3 (CRITICAL), 5/5 in flight +--- Phase 3: payment provider recovers, load drops --- +order-1 -> ACCEPTED: processed place order +order-2 -> ACCEPTED: processed place order +order-3 -> ACCEPTED: processed place order +order-4 -> ACCEPTED: processed place order +p3 -> ACCEPTED: processed checkout payment +[order-service] admitted r3 (LOW), 1/5 in flight +r3 -> ACCEPTED: processed prefetch recommendations +Summary: accepted=8, shed 2 requests in total: low=1, normal=1, critical=0 +``` + +## When to Use the Load Shedding Pattern in Java + +* A service has a known capacity (threads, connections, CPU) and traffic can exceed it, for example during marketing campaigns, retry storms or when a downstream dependency slows down. +* Latency matters more than throughput: it is better to answer some callers quickly with an error than to answer everybody late. +* Requests differ in importance and you want to protect critical flows (checkout, health checks, control plane traffic) at the expense of best-effort work. +* Callers are able to retry with backoff or to degrade gracefully when they receive a rejection. + +## Real-World Applications of Load Shedding Pattern in Java + +* Google's frontends shed load based on per-request criticality and measured CPU utilisation, as described in the Site Reliability Engineering book. +* Netflix's [concurrency-limits](https://github.com/Netflix/concurrency-limits) library rejects requests once the measured concurrency limit of a Java service is reached. +* Envoy and Istio provide admission control filters that reject requests when success rate or concurrency thresholds are exceeded. +* Resilience4j's `Bulkhead` and Hystrix's semaphore isolation reject calls when the configured number of concurrent calls is in flight. +* Netty and Tomcat reject connections when their accept queues are full rather than growing without bound. + +## Benefits and Trade-offs of Load Shedding Pattern + +Benefits: + +* Keeps latency predictable for the requests that are admitted instead of degrading every request. +* Prevents an overloaded service from exhausting memory, threads or connection pools and crashing. +* Stops overload from cascading: callers get an immediate answer and can fail over, degrade or back off. +* Priority-aware shedding protects the business-critical flows first. + +Trade-offs: + +* Some requests are deliberately rejected, so callers must be prepared to handle a rejection. +* Choosing capacity limits and priority thresholds requires measurement; limits that are too low waste capacity and limits that are too high do not protect the service. +* A static in-flight limit does not follow changes in hardware or in the cost of individual requests. Adaptive variants measure latency or CPU instead. +* Rejected callers that retry immediately can turn shedding into a retry storm, so shedding is usually combined with exponential backoff on the client side. + +## Related Java Design Patterns + +* [Rate Limiting](../rate-limiting-pattern): limits how many requests a client may send in a time window; load shedding instead reacts to the actual load of the server, whoever the client is. +* [Throttling](../throttling): slows callers down to a configured rate; load shedding rejects excess work outright once capacity is reached. +* [Backpressure](../backpressure): asks producers to slow down; load shedding is the last line of defence when producers cannot or do not slow down. +* [Queue-Based Load Leveling](../queue-based-load-leveling): buffers bursts in a queue; load shedding bounds that queue and drops what does not fit so that latency stays low. +* [Circuit Breaker](../circuit-breaker): protects a caller from a failing dependency; load shedding protects a service from its callers. +* [Fallback](../fallback): a natural companion, callers can answer a shed request with a cached or simplified response. + +## References and Credits + +* [Load Shedding pattern (microservices.io)](https://microservices.io/patterns/reliability/load-shedding.html) +* [Site Reliability Engineering, chapter Handling Overload (Google)](https://sre.google/sre-book/handling-overload/) +* [Release It! Design and Deploy Production-Ready Software (Michael T. Nygard)](https://www.amazon.com/gp/product/1680502395) +* [Using load shedding to avoid overload (Amazon Builders' Library)](https://aws.amazon.com/builders-library/using-load-shedding-to-avoid-overload/) +* [Netflix concurrency-limits](https://github.com/Netflix/concurrency-limits) diff --git a/microservices-load-shedding/etc/microservices-load-shedding.urm.png b/microservices-load-shedding/etc/microservices-load-shedding.urm.png new file mode 100644 index 0000000000000000000000000000000000000000..106ac68422b4de4da226f016f08ddf47695e8363 GIT binary patch literal 158059 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 !21+JpylSOMt2E9o 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 + - inFlight : AtomicInteger + - accepted : LongAdder + - shed : Map + + LoadShedder(maxInFlight : int, lowPriorityLimit : int, criticalReserve : int) + + acquire(request : Request) : int + + release() : void + + getMaxInFlight() : int + + getInFlight() : int + + getAccepted() : long + + getShed(priority : Priority) : long + + getTotalShed() : long + } + interface RequestHandler { + + handle(request : Request) : String {abstract} + } + class ShedGuardedService { + - name : String + - shedder : LoadShedder + - handler : RequestHandler + + ShedGuardedService(name : String, shedder : LoadShedder, handler : RequestHandler) + + handle(request : Request) : Response + } + class App { + + App() + + main(args : String[]) : void {static} + ~ simulatedPaymentProvider(paymentSlow : AtomicBoolean, paymentRecovered : CountDownLatch, entered : Semaphore, recoveryTimeout : Duration) : RequestHandler {static} + ~ awaitEntered(entered : Semaphore, count : int, timeout : Duration) : void {static} + ~ result(future : Future, timeout : Duration) : Response {static} + ~ shutdown(executor : ExecutorService, timeout : Duration) : void {static} + ~ report(response : Response) : void {static} + } +} +Response +-- Status +Request --> Priority +Response --> Status +Response ..> Request +LoadShedException --> Priority +LoadShedException ..> Request +LoadShedder ..> Priority +LoadShedder ..> Request +LoadShedder ..> LoadShedException +RequestHandler ..> Request +ShedGuardedService --> LoadShedder +ShedGuardedService --> RequestHandler +ShedGuardedService ..> Request +ShedGuardedService ..> Response +ShedGuardedService ..> LoadShedException +App ..> LoadShedder +App ..> ShedGuardedService +App ..> RequestHandler +@enduml diff --git a/microservices-load-shedding/pom.xml b/microservices-load-shedding/pom.xml new file mode 100644 index 000000000..33582143a --- /dev/null +++ b/microservices-load-shedding/pom.xml @@ -0,0 +1,70 @@ + + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.26.0-SNAPSHOT + + microservices-load-shedding + + + org.slf4j + slf4j-api + + + ch.qos.logback + logback-classic + + + org.junit.jupiter + junit-jupiter-engine + test + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + + + + com.iluwatar.loadshedding.App + + + + + + + + + diff --git a/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/App.java b/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/App.java new file mode 100644 index 000000000..f0ca4f95a --- /dev/null +++ b/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/App.java @@ -0,0 +1,194 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.loadshedding; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; +import lombok.extern.slf4j.Slf4j; + +/** + * Load Shedding is a resilience pattern for services that receive more work than they can handle. + * Instead of accepting every request and slowly drowning, the service measures its own load and + * proactively rejects excess requests at the door, so that the requests it does accept are served + * with normal latency and the process never runs out of threads, memory or connections. + * + *

The key ingredients demonstrated here are: + * + *

    + *
  • a capacity limit expressed as the number of requests in flight ({@link LoadShedder}), + *
  • fail-fast rejection: shed requests receive an immediate {@link Response.Status#REJECTED} + * answer instead of waiting in a queue ({@link ShedGuardedService}), + *
  • priority-aware shedding: low priority work is dropped first and a small reserve is kept for + * critical requests ({@link Priority}), + *
  • metrics that make the shedding decisions observable. + *
+ * + *

The demo runs an order service with capacity for five concurrent requests. Phase one shows + * normal operation. In phase two the payment provider becomes slow, four orders get stuck inside + * the service and probes of every priority show which of them are shed. In phase three the provider + * recovers, the stuck orders complete and new requests are admitted again. + */ +@Slf4j +public class App { + + private static final int CAPACITY = 5; + private static final int LOW_PRIORITY_LIMIT = 3; + private static final int CRITICAL_RESERVE = 1; + private static final int STUCK_ORDERS = 4; + private static final Duration WAIT = Duration.ofSeconds(5); + + /** + * Program entry point. + * + * @param args command line arguments, not used + * @throws InterruptedException if the demo is interrupted while waiting for the workers + */ + public static void main(String[] args) throws InterruptedException { + var shedder = new LoadShedder(CAPACITY, LOW_PRIORITY_LIMIT, CRITICAL_RESERVE); + var paymentSlow = new AtomicBoolean(false); + var paymentRecovered = new CountDownLatch(1); + var entered = new Semaphore(0); + var orderService = + new ShedGuardedService( + "order-service", + shedder, + simulatedPaymentProvider(paymentSlow, paymentRecovered, entered, WAIT)); + var executor = Executors.newCachedThreadPool(); + try { + LOGGER.info( + "Order service capacity: {} in flight, low priority shed at {}, {} slot reserved for" + + " critical requests", + CAPACITY, + LOW_PRIORITY_LIMIT, + CRITICAL_RESERVE); + + LOGGER.info("--- Phase 1: light load, every request is admitted ---"); + report(orderService.handle(new Request("r1", Priority.LOW, "prefetch recommendations"))); + report(orderService.handle(new Request("r2", Priority.NORMAL, "view cart"))); + + LOGGER.info("--- Phase 2: payment provider slows down, orders pile up ---"); + paymentSlow.set(true); + List> stuckOrders = new ArrayList<>(); + for (var i = 1; i <= STUCK_ORDERS; i++) { + var order = new Request("order-" + i, Priority.NORMAL, "place order"); + stuckOrders.add(executor.submit(() -> orderService.handle(order))); + } + awaitEntered(entered, STUCK_ORDERS, WAIT); + LOGGER.info( + "{} of {} slots busy, probing with every priority", shedder.getInFlight(), CAPACITY); + report(orderService.handle(new Request("p1", Priority.LOW, "prefetch recommendations"))); + report(orderService.handle(new Request("p2", Priority.NORMAL, "view cart"))); + var checkout = + executor.submit( + () -> orderService.handle(new Request("p3", Priority.CRITICAL, "checkout payment"))); + awaitEntered(entered, 1, WAIT); + + LOGGER.info("--- Phase 3: payment provider recovers, load drops ---"); + paymentSlow.set(false); + paymentRecovered.countDown(); + for (var order : stuckOrders) { + report(result(order, WAIT)); + } + report(result(checkout, WAIT)); + report(orderService.handle(new Request("r3", Priority.LOW, "prefetch recommendations"))); + + LOGGER.info( + "Summary: accepted={}, shed {} requests in total: low={}, normal={}, critical={}", + shedder.getAccepted(), + shedder.getTotalShed(), + shedder.getShed(Priority.LOW), + shedder.getShed(Priority.NORMAL), + shedder.getShed(Priority.CRITICAL)); + } finally { + shutdown(executor, WAIT); + } + } + + /** + * Business logic of the order service. While the payment provider is slow every admitted request + * blocks until the provider recovers, which is exactly the situation in which requests pile up + * and load shedding becomes necessary. The semaphore tells the demo how many requests are stuck. + */ + static RequestHandler simulatedPaymentProvider( + AtomicBoolean paymentSlow, + CountDownLatch paymentRecovered, + Semaphore entered, + Duration recoveryTimeout) { + return request -> { + if (paymentSlow.get()) { + // Signal the demo that one more request is now stuck behind the slow provider. + entered.release(); + try { + if (!paymentRecovered.await(recoveryTimeout.toMillis(), TimeUnit.MILLISECONDS)) { + throw new IllegalStateException("payment provider never recovered"); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new IllegalStateException("interrupted while processing " + request.id(), e); + } + } + return "processed " + request.description(); + }; + } + + /** Waits until the given number of requests are stuck inside the service. */ + static void awaitEntered(Semaphore entered, int count, Duration timeout) + throws InterruptedException { + if (!entered.tryAcquire(count, timeout.toMillis(), TimeUnit.MILLISECONDS)) { + throw new IllegalStateException("requests did not enter the service in time"); + } + } + + /** Collects the response of a request that was handled on a worker thread. */ + static Response result(Future future, Duration timeout) throws InterruptedException { + try { + return future.get(timeout.toMillis(), TimeUnit.MILLISECONDS); + } catch (ExecutionException | TimeoutException e) { + throw new IllegalStateException("worker failed", e); + } + } + + /** Stops the worker pool, forcing the shutdown if workers do not finish within the timeout. */ + static void shutdown(ExecutorService executor, Duration timeout) throws InterruptedException { + executor.shutdown(); + if (!executor.awaitTermination(timeout.toMillis(), TimeUnit.MILLISECONDS)) { + executor.shutdownNow(); + } + } + + static void report(Response response) { + LOGGER.info("{} -> {}: {}", response.requestId(), response.status(), response.message()); + } +} diff --git a/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/LoadShedException.java b/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/LoadShedException.java new file mode 100644 index 000000000..4015a509c --- /dev/null +++ b/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/LoadShedException.java @@ -0,0 +1,57 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.loadshedding; + +import lombok.Getter; + +/** + * Thrown by {@link LoadShedder#acquire(Request)} when a request must be shed. It is the in-process + * equivalent of an HTTP 503 "Service Unavailable" response: the service is healthy but has no spare + * capacity for this request right now, and the caller should back off and retry later. + */ +@Getter +public class LoadShedException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + private final String requestId; + private final Priority priority; + + /** + * Creates the exception for a shed request. + * + * @param request the request that was shed + * @param inFlight number of requests being processed at the moment of the decision + * @param limit admission limit that applies to the request's priority + */ + public LoadShedException(Request request, int inFlight, int limit) { + super( + String.format( + "Request %s shed: %d requests in flight, limit for %s priority is %d", + request.id(), inFlight, request.priority(), limit)); + this.requestId = request.id(); + this.priority = request.priority(); + } +} diff --git a/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/LoadShedder.java b/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/LoadShedder.java new file mode 100644 index 000000000..4cf4aad0e --- /dev/null +++ b/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/LoadShedder.java @@ -0,0 +1,146 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.loadshedding; + +import java.util.EnumMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.LongAdder; + +/** + * Admission controller that decides whether a request may enter the service. The decision is based + * on how many requests are already in flight and on the priority of the new request: + * + *

    + *
  • {@link Priority#LOW} requests are admitted only while the in-flight count is below the low + * priority limit, so they are the first to be shed when load builds up. + *
  • {@link Priority#NORMAL} requests are admitted while the in-flight count is below the hard + * capacity minus the reserve kept for critical work. + *
  • {@link Priority#CRITICAL} requests may use the full capacity, including the reserve. + *
+ * + *

Requests that cannot be admitted are rejected immediately with a {@link LoadShedException} + * rather than queued. Rejecting quickly costs almost nothing, whereas letting an unbounded queue + * grow would increase latency for every request and eventually exhaust memory or threads. + * + *

The class is thread-safe. Admission is lock-free: the in-flight count is updated with an + * atomic accumulator whose function refuses to increment past the limit, so concurrent callers can + * never push the in-flight count above the configured capacity. + */ +public class LoadShedder { + + private final int maxInFlight; + private final Map limits = new EnumMap<>(Priority.class); + private final AtomicInteger inFlight = new AtomicInteger(); + private final LongAdder accepted = new LongAdder(); + private final Map shed = new EnumMap<>(Priority.class); + + /** + * Creates a load shedder. + * + * @param maxInFlight hard capacity: the maximum number of requests processed concurrently + * @param lowPriorityLimit in-flight count at which low priority requests start being shed + * @param criticalReserve part of the capacity that only critical requests may use + */ + public LoadShedder(int maxInFlight, int lowPriorityLimit, int criticalReserve) { + if (maxInFlight <= 0) { + throw new IllegalArgumentException("maxInFlight must be positive"); + } + if (criticalReserve < 0 || criticalReserve >= maxInFlight) { + throw new IllegalArgumentException("criticalReserve must be between 0 and maxInFlight - 1"); + } + var normalLimit = maxInFlight - criticalReserve; + if (lowPriorityLimit <= 0 || lowPriorityLimit > normalLimit) { + throw new IllegalArgumentException( + "lowPriorityLimit must be between 1 and maxInFlight - criticalReserve"); + } + this.maxInFlight = maxInFlight; + limits.put(Priority.CRITICAL, maxInFlight); + limits.put(Priority.NORMAL, normalLimit); + limits.put(Priority.LOW, lowPriorityLimit); + for (var priority : Priority.values()) { + shed.put(priority, new LongAdder()); + } + } + + /** + * Tries to admit the request. On success the in-flight count is incremented and the caller must + * invoke {@link #release()} once the work is done. + * + * @param request the request asking for admission + * @return the in-flight count including this request, as observed at the moment of admission + * @throws LoadShedException if the service has no spare capacity for this priority + */ + public int acquire(Request request) { + var priority = request.priority(); + var limit = limits.get(priority); + // The accumulator is a pure function, so it is safe for the atomic to re-apply it under + // contention: the count is only incremented while it is below the limit for this priority. + var previous = + inFlight.getAndAccumulate( + 1, (current, increment) -> current >= limit ? current : current + increment); + if (previous >= limit) { + // Fail fast: the caller gets an immediate rejection instead of waiting in a queue. + shed.get(priority).increment(); + throw new LoadShedException(request, previous, limit); + } + accepted.increment(); + return previous + 1; + } + + /** + * Signals that a previously admitted request has finished, freeing one slot of capacity. The + * count is clamped at zero so that an unmatched release cannot make it negative and hand out more + * capacity than the service has. + */ + public void release() { + inFlight.updateAndGet(current -> Math.max(0, current - 1)); + } + + /** Hard capacity of the service. */ + public int getMaxInFlight() { + return maxInFlight; + } + + /** Number of requests currently being processed. */ + public int getInFlight() { + return inFlight.get(); + } + + /** Total number of requests admitted since creation. */ + public long getAccepted() { + return accepted.sum(); + } + + /** Number of requests of the given priority that were shed since creation. */ + public long getShed(Priority priority) { + return shed.get(priority).sum(); + } + + /** Total number of requests shed since creation, across all priorities. */ + public long getTotalShed() { + return shed.values().stream().mapToLong(LongAdder::sum).sum(); + } +} diff --git a/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/Priority.java b/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/Priority.java new file mode 100644 index 000000000..a2baca4d5 --- /dev/null +++ b/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/Priority.java @@ -0,0 +1,39 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.loadshedding; + +/** + * Importance of a request from the point of view of the service that receives it. When the service + * approaches its capacity the {@link LoadShedder} sheds the least important requests first, so that + * the work that matters most keeps flowing while excess load is rejected. + */ +public enum Priority { + /** Must be served whenever physically possible, for example checkout or health probes. */ + CRITICAL, + /** Regular user traffic. */ + NORMAL, + /** Best-effort work such as prefetching, analytics or background refreshes. */ + LOW +} diff --git a/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/Request.java b/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/Request.java new file mode 100644 index 000000000..7ff2681ce --- /dev/null +++ b/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/Request.java @@ -0,0 +1,36 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.loadshedding; + +/** + * An incoming unit of work. Besides its identity it carries the {@link Priority} the caller + * assigned to it, which is the only thing the {@link LoadShedder} needs to decide whether the + * request may enter the service. + * + * @param id unique identifier used in logs and responses + * @param priority importance of the request + * @param description human readable summary of the work + */ +public record Request(String id, Priority priority, String description) {} diff --git a/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/RequestHandler.java b/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/RequestHandler.java new file mode 100644 index 000000000..588475ae0 --- /dev/null +++ b/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/RequestHandler.java @@ -0,0 +1,41 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.loadshedding; + +/** + * The actual work a service performs for an admitted request. Kept as a functional interface so + * that the admission control in {@link ShedGuardedService} stays independent of the business logic. + */ +@FunctionalInterface +public interface RequestHandler { + + /** + * Processes the request. + * + * @param request an admitted request + * @return result to return to the caller + */ + String handle(Request request); +} diff --git a/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/Response.java b/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/Response.java new file mode 100644 index 000000000..494defd14 --- /dev/null +++ b/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/Response.java @@ -0,0 +1,55 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.loadshedding; + +/** + * Outcome returned to the caller. A shed request gets a {@link Status#REJECTED} response + * immediately instead of waiting in a queue, which is the fail-fast behaviour that keeps the + * service responsive under overload. + * + * @param requestId identifier of the request this response belongs to + * @param status whether the request was processed or shed + * @param message result of the work, or the reason the request was shed + */ +public record Response(String requestId, Status status, String message) { + + /** Result of admission control. */ + public enum Status { + /** The request was admitted and processed. */ + ACCEPTED, + /** The request was shed because the service is at capacity. Callers may retry later. */ + REJECTED + } + + /** Creates the response for a request that was processed. */ + public static Response accepted(Request request, String result) { + return new Response(request.id(), Status.ACCEPTED, result); + } + + /** Creates the fast-failure response for a request that was shed. */ + public static Response rejected(Request request, String reason) { + return new Response(request.id(), Status.REJECTED, reason); + } +} diff --git a/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/ShedGuardedService.java b/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/ShedGuardedService.java new file mode 100644 index 000000000..d43315d49 --- /dev/null +++ b/microservices-load-shedding/src/main/java/com/iluwatar/loadshedding/ShedGuardedService.java @@ -0,0 +1,84 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.loadshedding; + +import lombok.extern.slf4j.Slf4j; + +/** + * A service whose entry point is protected by a {@link LoadShedder}. Every request first asks the + * shedder for admission; requests that are shed receive a {@link Response.Status#REJECTED} response + * right away, admitted requests are handed to the {@link RequestHandler} and always release their + * capacity slot afterwards, even when the handler fails. + */ +@Slf4j +public class ShedGuardedService { + + private final String name; + private final LoadShedder shedder; + private final RequestHandler handler; + + /** + * Creates a guarded service. + * + * @param name service name used in log output + * @param shedder admission controller protecting the service + * @param handler business logic executed for admitted requests + */ + public ShedGuardedService(String name, LoadShedder shedder, RequestHandler handler) { + this.name = name; + this.shedder = shedder; + this.handler = handler; + } + + /** + * Handles the request if capacity allows, otherwise fails fast. + * + * @param request incoming request + * @return the handler result, or a rejection when the request was shed + */ + public Response handle(Request request) { + int inFlight; + try { + // The count is taken from the admission itself: reading it back afterwards could report a + // value that belongs to a concurrent request. + inFlight = shedder.acquire(request); + } catch (LoadShedException e) { + LOGGER.warn("[{}] shed {} ({}): {}", name, request.id(), request.priority(), e.getMessage()); + return Response.rejected(request, e.getMessage()); + } + LOGGER.info( + "[{}] admitted {} ({}), {}/{} in flight", + name, + request.id(), + request.priority(), + inFlight, + shedder.getMaxInFlight()); + try { + return Response.accepted(request, handler.handle(request)); + } finally { + shedder.release(); + } + } +} diff --git a/microservices-load-shedding/src/test/java/com/iluwatar/loadshedding/AppTest.java b/microservices-load-shedding/src/test/java/com/iluwatar/loadshedding/AppTest.java new file mode 100644 index 000000000..3a3b6a8f9 --- /dev/null +++ b/microservices-load-shedding/src/test/java/com/iluwatar/loadshedding/AppTest.java @@ -0,0 +1,177 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.loadshedding; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.time.Duration; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +class AppTest { + + private static final Duration SHORT = Duration.ofMillis(10); + private static final Duration GENEROUS = Duration.ofSeconds(1); + private static final Request REQUEST = new Request("r", Priority.NORMAL, "place order"); + + @AfterEach + void clearInterruptFlag() { + Thread.interrupted(); + } + + @Test + void shouldLaunchApp() { + assertDoesNotThrow(() -> App.main(new String[] {})); + } + + @Test + void shouldBeInstantiable() { + assertNotNull(new App(), "App should be instantiable"); + } + + @Test + void paymentProviderProcessesImmediatelyWhenHealthy() { + var entered = new Semaphore(0); + var handler = + App.simulatedPaymentProvider( + new AtomicBoolean(false), new CountDownLatch(1), entered, GENEROUS); + assertEquals("processed place order", handler.handle(REQUEST)); + assertEquals(0, entered.availablePermits()); + } + + @Test + void paymentProviderResumesOnceRecovered() { + var entered = new Semaphore(0); + var recovered = new CountDownLatch(0); + var handler = + App.simulatedPaymentProvider(new AtomicBoolean(true), recovered, entered, GENEROUS); + assertEquals("processed place order", handler.handle(REQUEST)); + assertEquals(1, entered.availablePermits()); + } + + @Test + void paymentProviderFailsWhenRecoveryTimesOut() { + var handler = + App.simulatedPaymentProvider( + new AtomicBoolean(true), new CountDownLatch(1), new Semaphore(0), SHORT); + var exception = assertThrows(IllegalStateException.class, () -> handler.handle(REQUEST)); + assertEquals("payment provider never recovered", exception.getMessage()); + } + + @Test + void paymentProviderRestoresInterruptFlagWhenInterruptedWhileSlow() { + var entered = new Semaphore(0); + var handler = + App.simulatedPaymentProvider( + new AtomicBoolean(true), new CountDownLatch(1), entered, GENEROUS); + Thread.currentThread().interrupt(); + var exception = assertThrows(IllegalStateException.class, () -> handler.handle(REQUEST)); + assertInstanceOf(InterruptedException.class, exception.getCause()); + assertTrue(Thread.interrupted()); + assertEquals(1, entered.availablePermits()); + } + + @Test + void awaitEnteredReturnsOncePermitsAreAvailable() { + var entered = new Semaphore(2); + assertDoesNotThrow(() -> App.awaitEntered(entered, 2, GENEROUS)); + assertEquals(0, entered.availablePermits()); + } + + @Test + void awaitEnteredFailsWhenNobodyEnters() { + var entered = new Semaphore(0); + var exception = + assertThrows(IllegalStateException.class, () -> App.awaitEntered(entered, 1, SHORT)); + assertEquals("requests did not enter the service in time", exception.getMessage()); + } + + @Test + void resultReturnsCompletedResponse() throws InterruptedException { + var response = Response.accepted(REQUEST, "done"); + assertEquals(response, App.result(CompletableFuture.completedFuture(response), GENEROUS)); + } + + @Test + void resultWrapsFailedWorker() { + var failed = CompletableFuture.failedFuture(new RuntimeException("boom")); + var exception = assertThrows(IllegalStateException.class, () -> App.result(failed, GENEROUS)); + assertEquals("worker failed", exception.getMessage()); + assertInstanceOf(RuntimeException.class, exception.getCause().getCause()); + } + + @Test + void resultWrapsWorkerThatNeverFinishes() { + var pending = new CompletableFuture(); + var exception = assertThrows(IllegalStateException.class, () -> App.result(pending, SHORT)); + assertEquals("worker failed", exception.getMessage()); + assertInstanceOf(TimeoutException.class, exception.getCause()); + } + + @Test + void shutdownWaitsForIdleExecutor() throws InterruptedException { + var executor = Executors.newSingleThreadExecutor(); + App.shutdown(executor, GENEROUS); + assertTrue(executor.isTerminated()); + } + + @Test + void shutdownForcesStopWhenWorkersIgnoreTheTimeout() throws InterruptedException { + var executor = Executors.newSingleThreadExecutor(); + var started = new CountDownLatch(1); + var interrupted = new CountDownLatch(1); + var release = new CountDownLatch(1); + executor.execute( + () -> { + started.countDown(); + while (release.getCount() > 0) { + try { + release.await(); + } catch (InterruptedException e) { + // A stubborn worker that keeps going despite the interrupt. + interrupted.countDown(); + } + } + }); + assertTrue(started.await(1, TimeUnit.SECONDS)); + App.shutdown(executor, SHORT); + assertTrue(executor.isShutdown()); + assertTrue(interrupted.await(1, TimeUnit.SECONDS)); + release.countDown(); + assertTrue(executor.awaitTermination(1, TimeUnit.SECONDS)); + } +} diff --git a/microservices-load-shedding/src/test/java/com/iluwatar/loadshedding/LoadShedderTest.java b/microservices-load-shedding/src/test/java/com/iluwatar/loadshedding/LoadShedderTest.java new file mode 100644 index 000000000..ffd9f4493 --- /dev/null +++ b/microservices-load-shedding/src/test/java/com/iluwatar/loadshedding/LoadShedderTest.java @@ -0,0 +1,201 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.loadshedding; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import org.junit.jupiter.api.Test; + +class LoadShedderTest { + + private static final int CAPACITY = 5; + private static final int LOW_LIMIT = 3; + private static final int RESERVE = 1; + + private final LoadShedder shedder = new LoadShedder(CAPACITY, LOW_LIMIT, RESERVE); + + private static Request request(Priority priority) { + return new Request("req-" + priority, priority, "test"); + } + + private void fill(int count) { + for (var i = 0; i < count; i++) { + shedder.acquire(request(Priority.CRITICAL)); + } + } + + @Test + void admitsEveryPriorityBelowLowPriorityLimit() { + fill(LOW_LIMIT - 1); + assertDoesNotThrow(() -> shedder.acquire(request(Priority.LOW))); + assertEquals(LOW_LIMIT, shedder.getInFlight()); + assertEquals(LOW_LIMIT, shedder.getAccepted()); + assertEquals(0, shedder.getTotalShed()); + } + + @Test + void shedsLowPriorityFirst() { + fill(LOW_LIMIT); + assertThrows(LoadShedException.class, () -> shedder.acquire(request(Priority.LOW))); + assertDoesNotThrow(() -> shedder.acquire(request(Priority.NORMAL))); + assertEquals(LOW_LIMIT + 1, shedder.getInFlight()); + assertEquals(1, shedder.getShed(Priority.LOW)); + assertEquals(0, shedder.getShed(Priority.NORMAL)); + } + + @Test + void keepsReserveForCriticalRequests() { + fill(CAPACITY - RESERVE); + assertThrows(LoadShedException.class, () -> shedder.acquire(request(Priority.NORMAL))); + assertDoesNotThrow(() -> shedder.acquire(request(Priority.CRITICAL))); + assertEquals(CAPACITY, shedder.getInFlight()); + assertEquals(1, shedder.getShed(Priority.NORMAL)); + assertEquals(0, shedder.getShed(Priority.CRITICAL)); + } + + @Test + void shedsCriticalRequestsAtHardCapacity() { + fill(CAPACITY); + assertThrows(LoadShedException.class, () -> shedder.acquire(request(Priority.CRITICAL))); + assertEquals(CAPACITY, shedder.getInFlight()); + assertEquals(1, shedder.getShed(Priority.CRITICAL)); + } + + @Test + void releaseFreesCapacity() { + fill(LOW_LIMIT); + assertThrows(LoadShedException.class, () -> shedder.acquire(request(Priority.LOW))); + shedder.release(); + assertDoesNotThrow(() -> shedder.acquire(request(Priority.LOW))); + assertEquals(LOW_LIMIT, shedder.getInFlight()); + } + + @Test + void unmatchedReleaseDoesNotDriveInFlightNegative() { + shedder.release(); + assertEquals(0, shedder.getInFlight()); + fill(CAPACITY); + assertThrows(LoadShedException.class, () -> shedder.acquire(request(Priority.CRITICAL))); + } + + @Test + void acquireReturnsInFlightCountIncludingTheAdmittedRequest() { + assertEquals(1, shedder.acquire(request(Priority.NORMAL))); + assertEquals(2, shedder.acquire(request(Priority.NORMAL))); + } + + @Test + void countsShedRequestsPerPriority() { + fill(CAPACITY); + assertThrows(LoadShedException.class, () -> shedder.acquire(request(Priority.LOW))); + assertThrows(LoadShedException.class, () -> shedder.acquire(request(Priority.LOW))); + assertThrows(LoadShedException.class, () -> shedder.acquire(request(Priority.NORMAL))); + assertThrows(LoadShedException.class, () -> shedder.acquire(request(Priority.CRITICAL))); + assertEquals(CAPACITY, shedder.getAccepted()); + assertEquals(2, shedder.getShed(Priority.LOW)); + assertEquals(1, shedder.getShed(Priority.NORMAL)); + assertEquals(1, shedder.getShed(Priority.CRITICAL)); + assertEquals(4, shedder.getTotalShed()); + } + + @Test + void exceptionDescribesTheDecision() { + fill(LOW_LIMIT); + var request = new Request("low-42", Priority.LOW, "test"); + var exception = assertThrows(LoadShedException.class, () -> shedder.acquire(request)); + assertEquals("low-42", exception.getRequestId()); + assertEquals(Priority.LOW, exception.getPriority()); + assertTrue(exception.getMessage().contains("low-42")); + assertTrue(exception.getMessage().contains("LOW")); + } + + @Test + void neverExceedsCapacityUnderConcurrentAdmission() throws InterruptedException { + var callers = 50; + var start = new CountDownLatch(1); + var done = new CountDownLatch(callers); + var admitted = new AtomicInteger(); + var executor = Executors.newFixedThreadPool(callers); + try { + for (var i = 0; i < callers; i++) { + executor.execute( + () -> { + try { + start.await(); + shedder.acquire(request(Priority.CRITICAL)); + admitted.incrementAndGet(); + } catch (LoadShedException expected) { + // shed + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } finally { + done.countDown(); + } + }); + } + start.countDown(); + assertTrue(done.await(10, TimeUnit.SECONDS)); + } finally { + executor.shutdownNow(); + } + assertEquals(CAPACITY, admitted.get()); + assertEquals(CAPACITY, shedder.getInFlight()); + assertEquals(callers - CAPACITY, shedder.getShed(Priority.CRITICAL)); + } + + @Test + void rejectsInvalidConfiguration() { + // maxInFlight must be positive + assertThrows(IllegalArgumentException.class, () -> new LoadShedder(0, 1, 0)); + // criticalReserve must be between 0 and maxInFlight - 1 + assertThrows(IllegalArgumentException.class, () -> new LoadShedder(5, 3, -1)); + assertThrows(IllegalArgumentException.class, () -> new LoadShedder(5, 3, 5)); + // lowPriorityLimit must be between 1 and maxInFlight - criticalReserve + assertThrows(IllegalArgumentException.class, () -> new LoadShedder(5, 0, 1)); + assertThrows(IllegalArgumentException.class, () -> new LoadShedder(5, 5, 1)); + } + + @Test + void acceptsBoundaryConfiguration() { + assertDoesNotThrow(() -> new LoadShedder(5, 4, 1)); + var noReserve = new LoadShedder(5, 5, 0); + fillWith(noReserve, Priority.LOW, 5); + assertEquals(5, noReserve.getInFlight()); + assertThrows(LoadShedException.class, () -> noReserve.acquire(request(Priority.CRITICAL))); + } + + private static void fillWith(LoadShedder target, Priority priority, int count) { + for (var i = 0; i < count; i++) { + target.acquire(request(priority)); + } + } +} diff --git a/microservices-load-shedding/src/test/java/com/iluwatar/loadshedding/ShedGuardedServiceTest.java b/microservices-load-shedding/src/test/java/com/iluwatar/loadshedding/ShedGuardedServiceTest.java new file mode 100644 index 000000000..87c847196 --- /dev/null +++ b/microservices-load-shedding/src/test/java/com/iluwatar/loadshedding/ShedGuardedServiceTest.java @@ -0,0 +1,80 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.loadshedding; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.util.concurrent.atomic.AtomicBoolean; +import org.junit.jupiter.api.Test; + +class ShedGuardedServiceTest { + + private final LoadShedder shedder = new LoadShedder(2, 1, 0); + + @Test + void returnsHandlerResultWhenAdmitted() { + var service = new ShedGuardedService("svc", shedder, request -> "done " + request.id()); + var response = service.handle(new Request("a", Priority.NORMAL, "work")); + assertEquals(new Response("a", Response.Status.ACCEPTED, "done a"), response); + assertEquals(0, shedder.getInFlight()); + } + + @Test + void returnsRejectionWithoutInvokingHandlerWhenShed() { + var handlerCalled = new AtomicBoolean(); + var service = + new ShedGuardedService( + "svc", + shedder, + request -> { + handlerCalled.set(true); + return "unexpected"; + }); + shedder.acquire(new Request("occupied", Priority.NORMAL, "work")); + var response = service.handle(new Request("b", Priority.LOW, "work")); + assertEquals(Response.Status.REJECTED, response.status()); + assertEquals("b", response.requestId()); + assertFalse(handlerCalled.get()); + assertEquals(1, shedder.getInFlight()); + assertEquals(1, shedder.getShed(Priority.LOW)); + } + + @Test + void releasesCapacityWhenHandlerFails() { + var service = + new ShedGuardedService( + "svc", + shedder, + request -> { + throw new IllegalStateException("boom"); + }); + assertThrows( + IllegalStateException.class, + () -> service.handle(new Request("c", Priority.NORMAL, "work"))); + assertEquals(0, shedder.getInFlight()); + } +} diff --git a/pom.xml b/pom.xml index a71630d28..266c02fcb 100644 --- a/pom.xml +++ b/pom.xml @@ -260,6 +260,7 @@ rate-limiting-pattern fallback onion-architecture + microservices-load-shedding