Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

docs: touchups for resilience features #3106

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion servicetalk-examples/docs/modules/ROOT/pages/http/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -299,10 +299,33 @@ Async `Hello World` example that demonstrates how retry can be requested for a s
Async `Hello World` example that demonstrates how retry can be requested for a multi-address client.

[#TrafficResiliency]
= Traffic Resiliency
== Traffic Resiliency

Some examples that use the traffic resiliency features.

- link:{source-root}/servicetalk-examples/http/traffic-resilience/src/main/java/io/servicetalk/examples/http/traffic/resilience/GradientObservabilityExample.java[GradientObservabilityExample] -
An example that demonstrates using the observer pattern to instrument the gradient capacity limiter.
- link:{source-root}/servicetalk-examples/http/traffic-resilience/src/main/java/io/servicetalk/examples/http/traffic/resilience/TrafficResilienceClientBreakersExample.java[TrafficResilienceClientBreakersExample] -
A client that uses request metadata to select the correct circuit breaker.
- link:{source-root}/servicetalk-examples/http/traffic-resilience/src/main/java/io/servicetalk/examples/http/traffic/resilience/TrafficResilienceClientPeerRejectionsExample.java[TrafficResilienceClientPeerRejectionsExample] -
A client which configures what constitutes a rejection based on response status code.
- link:{source-root}/servicetalk-examples/http/traffic-resilience/src/main/java/io/servicetalk/examples/http/traffic/resilience/TrafficResilienceClientPeerRejectionsPassthroughExample.java[TrafficResilienceClientPeerRejectionsPassthroughExample] -
A client which configures which responses will affect the capacity limiter but still pass through to the underlying
client.
- link:{source-root}/servicetalk-examples/http/traffic-resilience/src/main/java/io/servicetalk/examples/http/traffic/resilience/TrafficResilienceClientPeerRejectionsRetryExample.java[TrafficResilienceClientPeerRejectionsRetryExample] -
A client which configures the resilience filters to signal an appropriate delay to the retry filter.
- link:{source-root}/servicetalk-examples/http/traffic-resilience/src/main/java/io/servicetalk/examples/http/traffic/resilience/TrafficResilienceServerClassificationExample.java[TrafficResilienceServerClassificationExample] -
A server that specifies the importance of requests based on the request metadata.
- link:{source-root}/servicetalk-examples/http/traffic-resilience/src/main/java/io/servicetalk/examples/http/traffic/resilience/TrafficResilienceServerExample.java[TrafficResilienceServerExample] -
A server that uses the dynamic gradient capacity limiter.
- link:{source-root}/servicetalk-examples/http/traffic-resilience/src/main/java/io/servicetalk/examples/http/traffic/resilience/TrafficResilienceServerPartitionExample.java[TrafficResilienceServerPartitionExample] -
A server that uses two separate capacity limiters, selected based on request metadata.
- link:{source-root}/servicetalk-examples/http/traffic-resilience/src/main/java/io/servicetalk/examples/http/traffic/resilience/TrafficResilienceServerQuotasExample.java[TrafficResilienceServerQuotasExample] -
A server that uses fixed capacity limiters based on the customer identity, as determined by the request metadata.
- link:{source-root}/servicetalk-examples/http/traffic-resilience/src/main/java/io/servicetalk/examples/http/traffic/resilience/TrafficResilienceServerStopAcceptingExample.java[TrafficResilienceServerStopAcceptingExample] -
A server that stops accepting new connections when it reaches its rejection threshold.
- link:{source-root}/servicetalk-examples/http/traffic-resilience/src/main/java/io/servicetalk/examples/http/traffic/resilience/TrafficResilienceServerTerminalsExample.java[TrafficResilienceServerTerminalsExample] -
An example that demonstrates custom handling of tickets on error conditions.

[#HTTP2]
== HTTP/2
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@

import static io.servicetalk.capacity.limiter.api.CapacityLimiters.dynamicGradientOptimizeForThroughput;

/**
* An example that demonstrates using the observer pattern to instrument the gradient capacity limiter.
*/
public final class GradientObservabilityExample {

@SuppressWarnings({"UseOfSystemOutOrSystemErr", "PMD.SystemPrintln"})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,33 +18,39 @@
import io.servicetalk.capacity.limiter.api.CapacityLimiters;
import io.servicetalk.circuit.breaker.api.CircuitBreaker;
import io.servicetalk.circuit.breaker.resilience4j.Resilience4jAdapters;
import io.servicetalk.http.api.HttpClient;
import io.servicetalk.http.api.BlockingHttpClient;
import io.servicetalk.http.netty.HttpClients;
import io.servicetalk.traffic.resilience.http.TrafficResilienceHttpClientFilter;

/**
* An example demonstrating the selection of the appropriate circuit breaker based on request metadata.
*/
public final class TrafficResilienceClientBreakersExample {
public static void main(String[] args) throws Exception {
final TrafficResilienceHttpClientFilter resilienceFilter =
new TrafficResilienceHttpClientFilter.Builder(() -> CapacityLimiters.dynamicGradient().build())
.circuitBreakerPartitions(() -> {
final CircuitBreaker breakerForPathA = Resilience4jAdapters.fromCircuitBreaker(
io.github.resilience4j.circuitbreaker.CircuitBreaker.ofDefaults("example-a"));
final CircuitBreaker breakerForPathB = Resilience4jAdapters.fromCircuitBreaker(
final CircuitBreaker breakerForNonAPaths = Resilience4jAdapters.fromCircuitBreaker(
io.github.resilience4j.circuitbreaker.CircuitBreaker.ofDefaults("example-b"));

return requestMetaData -> {
if ("/A".equals(requestMetaData.requestTarget())) {
return breakerForPathA;
}
return breakerForPathB;
return breakerForNonAPaths;
};
})
.build();

try (HttpClient client = HttpClients.forSingleAddress("localhost", 8080)
try (BlockingHttpClient client = HttpClients.forSingleAddress("localhost", 8080)
.appendClientFilter(resilienceFilter)
.build()) {
// use client
.build().asBlockingClient()) {
// Will use breakerForPathA
client.request(client.get("/A"));
// Will use breakerForNonAPaths
client.request(client.get("/other"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package io.servicetalk.examples.http.traffic.resilience;

import io.servicetalk.capacity.limiter.api.CapacityLimiters;
import io.servicetalk.http.api.BlockingHttpClient;
import io.servicetalk.http.netty.HttpClients;
import io.servicetalk.traffic.resilience.http.ClientPeerRejectionPolicy;
import io.servicetalk.traffic.resilience.http.TrafficResilienceHttpClientFilter;
Expand All @@ -24,8 +25,11 @@
import static io.servicetalk.http.api.HttpResponseStatus.SERVICE_UNAVAILABLE;
import static io.servicetalk.http.api.HttpResponseStatus.TOO_MANY_REQUESTS;

/**
* An example demonstrating the configuration of what constitutes a rejection based on response status code.
*/
public final class TrafficResilienceClientPeerRejectionsExample {
public static void main(String[] args) {
public static void main(String[] args) throws Exception {
final TrafficResilienceHttpClientFilter resilienceFilter =
new TrafficResilienceHttpClientFilter.Builder(() -> CapacityLimiters.dynamicGradient().build())
.rejectionPolicy(ClientPeerRejectionPolicy.ofRejection(metaData ->
Expand All @@ -34,8 +38,10 @@ public static void main(String[] args) {
metaData.status().code() == SERVICE_UNAVAILABLE.code()))
.build();

HttpClients.forSingleAddress("localhost", 8080)
try (BlockingHttpClient client = HttpClients.forSingleAddress("localhost", 8080)
.appendClientFilter(resilienceFilter)
.build();
.build().asBlockingClient()) {
client.request(client.get("/foo"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
import static io.servicetalk.http.api.HttpResponseStatus.SERVICE_UNAVAILABLE;
import static io.servicetalk.http.api.HttpResponseStatus.TOO_MANY_REQUESTS;

/**
* A client which configures which responses will affect the capacity limiter but still pass through to the underlying
* client.
bryce-anderson marked this conversation as resolved.
Show resolved Hide resolved
*/
public final class TrafficResilienceClientPeerRejectionsPassthroughExample {
public static void main(String[] args) {
final TrafficResilienceHttpClientFilter resilienceFilter =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
import static java.time.Duration.ofMillis;
import static java.time.Duration.ofSeconds;

/**
* A client which configures the resilience filters to signal an appropriate delay to the retry filter.
*/
public final class TrafficResilienceClientPeerRejectionsRetryExample {
public static void main(String[] args) {
final TrafficResilienceHttpClientFilter resilienceFilter =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
import io.servicetalk.http.netty.HttpServers;
import io.servicetalk.traffic.resilience.http.TrafficResilienceHttpServiceFilter;

/**
* A server that specifies the importance of requests based on the request metadata.
*/
public final class TrafficResilienceServerClassificationExample {

public static void main(String[] args) throws Exception {
Expand All @@ -28,8 +31,9 @@ public static void main(String[] args) throws Exception {
.classifier(() -> (meta) -> "/health".equals(meta.requestTarget()) ? () -> 20 : () -> 100)
.build();

HttpServers.forPort(0)
HttpServers.forPort(8080)
.appendNonOffloadingServiceFilter(resilienceFilter)
.listenAndAwait((ctx, request, responseFactory) -> Single.succeeded(responseFactory.ok()));
.listenAndAwait((ctx, request, responseFactory) -> Single.succeeded(responseFactory.ok()))
.awaitShutdown();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,19 @@
import io.servicetalk.http.netty.HttpServers;
import io.servicetalk.traffic.resilience.http.TrafficResilienceHttpServiceFilter;

/**
* A server that uses the dynamic gradient capacity limiter.
*/
public final class TrafficResilienceServerExample {

public static void main(String[] args) throws Exception {
final TrafficResilienceHttpServiceFilter resilienceFilter =
new TrafficResilienceHttpServiceFilter.Builder(() -> CapacityLimiters.dynamicGradient().build())
.build();

HttpServers.forPort(0)
HttpServers.forPort(8080)
.appendNonOffloadingServiceFilter(resilienceFilter)
.listenAndAwait((ctx, request, responseFactory) -> Single.succeeded(responseFactory.ok()));
.listenAndAwait((ctx, request, responseFactory) -> Single.succeeded(responseFactory.ok()))
.awaitShutdown();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@

import static io.servicetalk.http.api.HttpRequestMethod.POST;

/**
* A server that uses two separate capacity limiters, selected based on request metadata.
*/
public final class TrafficResilienceServerPartitionExample {

public static void main(String[] args) throws Exception {
Expand All @@ -33,8 +36,9 @@ public static void main(String[] args) throws Exception {
return meta -> meta.method() == POST ? setLimiter : getLimiter;
}, true).build();

HttpServers.forPort(0)
HttpServers.forPort(8080)
.appendNonOffloadingServiceFilter(resilienceFilter)
.listenAndAwait((ctx, request, responseFactory) -> Single.succeeded(responseFactory.ok()));
.listenAndAwait((ctx, request, responseFactory) -> Single.succeeded(responseFactory.ok()))
.awaitShutdown();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
import static io.servicetalk.buffer.api.CharSequences.contentEqualsIgnoreCase;
import static java.util.Arrays.asList;

/**
* A server that uses fixed capacity limiters based on the customer identity, as determined by the request metadata.
*/
public final class TrafficResilienceServerQuotasExample {
static final CharSequence CUSTOMER = "x-customer";
static final CharSequence CUSTOMER_X = "X";
Expand All @@ -39,8 +42,9 @@ public static void main(String[] args) throws Exception {
}, true)
.build();

HttpServers.forPort(0)
HttpServers.forPort(8080)
.appendNonOffloadingServiceFilter(resilienceFilter)
.listenAndAwait((ctx, request, responseFactory) -> Single.succeeded(responseFactory.ok()));
.listenAndAwait((ctx, request, responseFactory) -> Single.succeeded(responseFactory.ok()))
.awaitShutdown();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
import io.servicetalk.traffic.resilience.http.ServiceRejectionPolicy;
import io.servicetalk.traffic.resilience.http.TrafficResilienceHttpServiceFilter;

/**
* A server that stops accepting new connections when it reaches its rejection threshold.
*/
public final class TrafficResilienceServerStopAcceptingExample {

public static void main(String[] args) throws Exception {
Expand All @@ -33,8 +36,9 @@ public static void main(String[] args) throws Exception {
.rejectionPolicy(rejectionPolicy)
.build();

HttpServers.forPort(0)
HttpServers.forPort(8080)
.appendNonOffloadingServiceFilter(resilienceFilter)
.listenAndAwait((ctx, request, responseFactory) -> Single.succeeded(responseFactory.ok()));
.listenAndAwait((ctx, request, responseFactory) -> Single.succeeded(responseFactory.ok()))
.awaitShutdown();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@

import java.util.concurrent.RejectedExecutionException;

/**
* An example that demonstrates custom handling of tickets on error conditions.
*/
public final class TrafficResilienceServerTerminalsExample {

public static void main(String[] args) throws Exception {
Expand All @@ -36,8 +39,9 @@ public static void main(String[] args) throws Exception {
})
.build();

HttpServers.forPort(0)
HttpServers.forPort(8080)
.appendNonOffloadingServiceFilter(resilienceFilter)
.listenAndAwait((ctx, request, responseFactory) -> Single.succeeded(responseFactory.ok()));
.listenAndAwait((ctx, request, responseFactory) -> Single.succeeded(responseFactory.ok()))
bryce-anderson marked this conversation as resolved.
Show resolved Hide resolved
.awaitShutdown();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ This solution is heavily tunable for power users, but we provide a few
link:https://github.com/apple/servicetalk/blob/main/servicetalk-capacity-limiter-api/src/main/java/io/servicetalk/capacity/limiter/api/CapacityLimiters.java[configuration profiles]
by default, that attempt to please a couple of different expectations (e.g. favouring throughput or latency).

* link:{source-root}/servicetalk-examples/http/traffic-resilience/src/main/java/io/servicetalk/examples/http/traffic/resilience/GradientExample.java[Gradient example]

[quote]
----
All limiters we discussed so far, have their use cases, and the contract is public allowing for more power users to
Expand Down
Loading