mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-08-21 08:26:16 +00:00
docs: update throttling
This commit is contained in:
+35
-30
@@ -39,7 +39,6 @@ In this example a young human and an old dwarf walk into a bar. They start order
|
|||||||
`BarCustomer` class presents the clients of the `Bartender` API. `CallsCount` tracks the number of calls per `BarCustomer`.
|
`BarCustomer` class presents the clients of the `Bartender` API. `CallsCount` tracks the number of calls per `BarCustomer`.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class BarCustomer {
|
public class BarCustomer {
|
||||||
|
|
||||||
@@ -55,7 +54,9 @@ public class BarCustomer {
|
|||||||
callsCount.addTenant(name);
|
callsCount.addTenant(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```java
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public final class CallsCount {
|
public final class CallsCount {
|
||||||
private final Map<String, AtomicLong> tenantCallsCount = new ConcurrentHashMap<>();
|
private final Map<String, AtomicLong> tenantCallsCount = new ConcurrentHashMap<>();
|
||||||
@@ -85,7 +86,9 @@ Next, the service that the tenants are calling is introduced. To track the call
|
|||||||
public interface Throttler {
|
public interface Throttler {
|
||||||
void start();
|
void start();
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```java
|
||||||
public class ThrottleTimerImpl implements Throttler {
|
public class ThrottleTimerImpl implements Throttler {
|
||||||
|
|
||||||
private final int throttlePeriod;
|
private final int throttlePeriod;
|
||||||
@@ -142,36 +145,42 @@ class Bartender {
|
|||||||
Now it is possible to see the full example in action. `BarCustomer` young human is rate-limited to 2 calls per second and the old dwarf to 4.
|
Now it is possible to see the full example in action. `BarCustomer` young human is rate-limited to 2 calls per second and the old dwarf to 4.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public static void main(String[] args) {
|
@Slf4j
|
||||||
var callsCount = new CallsCount();
|
public class App {
|
||||||
var human = new BarCustomer("young human", 2, callsCount);
|
|
||||||
var dwarf = new BarCustomer("dwarf soldier", 4, callsCount);
|
|
||||||
|
|
||||||
var executorService = Executors.newFixedThreadPool(2);
|
public static void main(String[] args) {
|
||||||
|
var callsCount = new CallsCount();
|
||||||
|
var human = new BarCustomer("young human", 2, callsCount);
|
||||||
|
var dwarf = new BarCustomer("dwarf soldier", 4, callsCount);
|
||||||
|
|
||||||
executorService.execute(() -> makeServiceCalls(human, callsCount));
|
var executorService = Executors.newFixedThreadPool(2);
|
||||||
executorService.execute(() -> makeServiceCalls(dwarf, callsCount));
|
|
||||||
|
|
||||||
executorService.shutdown();
|
executorService.execute(() -> makeServiceCalls(human, callsCount));
|
||||||
try {
|
executorService.execute(() -> makeServiceCalls(dwarf, callsCount));
|
||||||
executorService.awaitTermination(10, TimeUnit.SECONDS);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
LOGGER.error("Executor service terminated: {}", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void makeServiceCalls(BarCustomer barCustomer, CallsCount callsCount) {
|
executorService.shutdown();
|
||||||
var timer = new ThrottleTimerImpl(1000, callsCount);
|
|
||||||
var service = new Bartender(timer, callsCount);
|
|
||||||
// Sleep is introduced to keep the output in check and easy to view and analyze the results.
|
|
||||||
IntStream.range(0, 50).forEach(i -> {
|
|
||||||
service.orderDrink(barCustomer);
|
|
||||||
try {
|
try {
|
||||||
Thread.sleep(100);
|
if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) {
|
||||||
|
executorService.shutdownNow();
|
||||||
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOGGER.error("Thread interrupted: {}", e.getMessage());
|
executorService.shutdownNow();
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
private static void makeServiceCalls(BarCustomer barCustomer, CallsCount callsCount) {
|
||||||
|
var timer = new ThrottleTimerImpl(1000, callsCount);
|
||||||
|
var service = new Bartender(timer, callsCount);
|
||||||
|
// Sleep is introduced to keep the output in check and easy to view and analyze the results.
|
||||||
|
IntStream.range(0, 50).forEach(i -> {
|
||||||
|
service.orderDrink(barCustomer);
|
||||||
|
try {
|
||||||
|
Thread.sleep(100);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
LOGGER.error("Thread interrupted: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -202,10 +211,6 @@ An excerpt from the example's console output:
|
|||||||
18:46:37.148 [pool-1-thread-2] ERROR com.iluwatar.throttling.Bartender - I'm sorry dwarf soldier, you've had enough for today!
|
18:46:37.148 [pool-1-thread-2] ERROR com.iluwatar.throttling.Bartender - I'm sorry dwarf soldier, you've had enough for today!
|
||||||
```
|
```
|
||||||
|
|
||||||
## Class diagram
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## Applicability
|
## Applicability
|
||||||
|
|
||||||
* You need to protect resources from being overwhelmed by too many requests.
|
* You need to protect resources from being overwhelmed by too many requests.
|
||||||
@@ -239,5 +244,5 @@ Trade-offs:
|
|||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
* [Throttling pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/throttling)
|
* [Throttling pattern (Microsoft)](https://docs.microsoft.com/en-us/azure/architecture/patterns/throttling)
|
||||||
* [Cloud Design Patterns: Prescriptive Architecture Guidance for Cloud Applications (Microsoft patterns & practices)](https://www.amazon.com/gp/product/B00ITGHBBS/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=B00ITGHBBS&linkId=12aacdd0cec04f372e7152689525631a)
|
* [Cloud Design Patterns: Prescriptive Architecture Guidance for Cloud Applications](https://amzn.to/4dLvowg)
|
||||||
|
|||||||
Reference in New Issue
Block a user