-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from aerospike-examples/dev
Merge from dev
- Loading branch information
Showing
7 changed files
with
602 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# This workflow will build the Java project with Maven | ||
|
||
name: Build | ||
|
||
on: | ||
push: | ||
branches: [ "main", "dev" ] | ||
pull_request: | ||
branches: [ "main", "dev" ] | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Set up JDK | ||
uses: actions/setup-java@v4 | ||
with: | ||
java-version: '21' | ||
distribution: 'zulu' | ||
cache: maven | ||
- name: Build with Maven | ||
run: mvn package |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
# This workflow will build the Java project with Maven and create a Github release | ||
|
||
name: Release | ||
on: | ||
push: | ||
branches: [ "main" ] | ||
pull_request: | ||
branches: [ "main" ] | ||
|
||
permissions: | ||
contents: read | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Set up JDK | ||
uses: actions/setup-java@v4 | ||
with: | ||
java-version: '21' | ||
distribution: 'zulu' | ||
cache: maven | ||
- name: Build with Maven | ||
run: mvn package | ||
- name: Upload jar | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: maven-build-jar | ||
path: target/aerospike-circuit-breaker-*-with-dependencies.jar | ||
release: | ||
runs-on: ubuntu-latest | ||
needs: | ||
- build | ||
permissions: | ||
contents: write | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Download jar | ||
uses: actions/download-artifact@v4 | ||
with: | ||
name: maven-build-jar | ||
path: target/aerospike-circuit-breaker-*-with-dependencies.jar | ||
- name: Release to Github | ||
uses: ncipollo/release-action@v1 | ||
with: | ||
artifacts: "target/aerospike-circuit-breaker-*-with-dependencies.jar" | ||
generateReleaseNotes: true | ||
draft: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,32 @@ | ||
# Compiled class file | ||
*.class | ||
target/ | ||
!.mvn/wrapper/maven-wrapper.jar | ||
!**/src/main/**/target/ | ||
!**/src/test/**/target/ | ||
|
||
# Log file | ||
*.log | ||
### IntelliJ IDEA ### | ||
.idea/ | ||
|
||
# BlueJ files | ||
*.ctxt | ||
### Eclipse ### | ||
.apt_generated | ||
.classpath | ||
.factorypath | ||
.project | ||
.settings | ||
.springBeans | ||
.sts4-cache | ||
|
||
# Mobile Tools for Java (J2ME) | ||
.mtj.tmp/ | ||
### NetBeans ### | ||
/nbproject/private/ | ||
/nbbuild/ | ||
/dist/ | ||
/nbdist/ | ||
/.nb-gradle/ | ||
build/ | ||
!**/src/main/**/build/ | ||
!**/src/test/**/build/ | ||
|
||
# Package Files # | ||
*.jar | ||
*.war | ||
*.nar | ||
*.ear | ||
*.zip | ||
*.tar.gz | ||
*.rar | ||
### VS Code ### | ||
.vscode/ | ||
|
||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml | ||
hs_err_pid* | ||
replay_pid* | ||
### Mac OS ### | ||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
Aerospike Circuit Breaker in Java | ||
================================= | ||
|
||
[![Aerospike Enterprise](https://img.shields.io/badge/Aerospike-Enterprise_Editition-C22127?labelColor=white&logo=aerospike&logoColor=C22127&style=flat)](https://aerospike.com/download/#aerospike-server-enterprise-edition) | ||
[![Aerospike Community](https://img.shields.io/badge/Aerospike-Community_Editition-C22127?labelColor=white&logo=aerospike&logoColor=C22127&style=flat)](https://aerospike.com/download/#aerospike-server-community-edition) | ||
[![Aerospike Java](https://img.shields.io/badge/Aerospike-Java_Client-C22127?labelColor=white&logo=aerospike&logoColor=C22127&style=flat)](https://aerospike.com/download/#aerospike-clients-java-client-library) | ||
|
||
[![Build](https://github.com/aerospike-examples/aerospike-circuit-breaker-java/actions/workflows/build.yml/badge.svg)](https://github.com/aerospike-examples/aerospike-circuit-breaker-java/actions/workflows/build.yml) | ||
|
||
[Aerospike](http://www.aerospike.com) is a low-latency distributed NoSQL database. This project is an example Java application that demonstrates how the "circuit breaker" design pattern is implemented in Aerospike. See my blog post [Aerospike Circuit Breaker Pattern](https://aerospike.com/blog/) for a complete discussion. | ||
|
||
This project uses the asynchronous API of the Aerospike Java Client. You can read about how that works in [Understanding Asynchronous Operations](https://aerospike.com/developer/tutorials/java/async_ops) on Aerospike Developer Hub. | ||
|
||
Questions, comments, feedback? Find me in the `#ask-the-community` channel in the [Aerospike Developer Discord server](https://discord.com/invite/NfC93wJEJU). | ||
|
||
Set Up | ||
------ | ||
|
||
Clone the repo and build the package: | ||
|
||
```bash | ||
git clone https://github.com/aerospike-examples/aerospike-circuit-breaker-java.git | ||
cd aerospike-circuit-breaker-java | ||
mvn package | ||
``` | ||
|
||
For local testing you can run [Aerospike Database Enterprise in Docker](https://aerospike.com/docs/deploy_guides/docker/). Aerospike Enterprise comes with a free developer license for single-node configuration which is used for this example project. | ||
|
||
The following command will run Aerospike Database Enterprise using the free developer license in a container listening on port | ||
|
||
```bash | ||
docker run -tid --name aerospike -p 3000:3000 \ | ||
-v "$(pwd)/docker/opt/aerospike/conf":/opt/aerospike/conf \ | ||
-e "FEATURE_KEY_FILE=/etc/aerospike/features.conf" \ | ||
aerospike/aerospike-server-enterprise \ | ||
--config-file /opt/aerospike/conf/aerospike.conf | ||
``` | ||
|
||
Run the jar file passing in 3 command-line arguments: `HOST:PORT`, `MAX_ERROR_RATE`, and `WRITE_OPS`. The application will connect to the Aerospike Database running in Docker, set the [maxErrorRate](https://javadoc.io/doc/com.aerospike/aerospike-client/latest/com/aerospike/client/policy/ClientPolicy.html#maxErrorRate) policy to `MAX_ERROR_RATE`, and perform the number asynchronous write operations indicated by `WRITE_OPS`. | ||
|
||
For example, run the application against the Aerospike Database running in docker at `172.17.0.2` on port `3000`, set [maxErrorRate](https://javadoc.io/doc/com.aerospike/aerospike-client/latest/com/aerospike/client/policy/ClientPolicy.html#maxErrorRate) to `100`, and perform 10,000 write operations: | ||
|
||
```bash | ||
java -jar \ | ||
target/aerospike-circuit-breaker-java-1.0-SNAPSHOT-jar-with-dependencies.jar \ | ||
172.17.0.2:3000 100 10000 | ||
``` | ||
|
||
Output | ||
------ | ||
|
||
The application will output a summary at the end of the run: | ||
|
||
``` | ||
Run time: 0.283 seconds | ||
Successful writes: 10000 | ||
Connection errors: 0 | ||
Timeout errors: 0 | ||
Max errors exceeded: 0 | ||
Node unavailable errors: 0 | ||
Other errors: 0 | ||
Connections opened: 96 | ||
Connections closed: 0 | ||
``` | ||
|
||
Demonstrating the Circuit Breaker | ||
--------------------------------- | ||
|
||
### Step 1 - Run a steady-state baseline | ||
|
||
Perform 5 million write operations with `maxErrorRate=0` (disabled): | ||
|
||
```bash | ||
java -jar \ | ||
target/aerospike-circuit-breaker-java-1.0-SNAPSHOT-jar-with-dependencies.jar \ | ||
172.17.0.2:3000 0 5000000 | ||
``` | ||
|
||
The output shows that all write operations were successful: | ||
|
||
``` | ||
Run time: 20.354 seconds | ||
Successful writes: 5000000 | ||
Connection errors: 0 | ||
Timeout errors: 0 | ||
Max errors exceeded: 0 | ||
Node unavailable errors: 0 | ||
Other errors: 0 | ||
Connections opened: 96 | ||
Connections closed: 0 | ||
``` | ||
|
||
### Step 2 - Run with a 10 second period of latency without circuit breaker | ||
|
||
Perform 5 million write operations with `maxErrorRate=0` (disabled). __While the application is running__, add 20ms of latency to the Docker network interface, wait ~10 seconds, then remove the latency: | ||
|
||
_Terminal 1_ | ||
```bash | ||
java -jar \ | ||
target/aerospike-circuit-breaker-java-1.0-SNAPSHOT-jar-with-dependencies.jar \ | ||
172.17.0.2:3000 0 5000000 | ||
``` | ||
|
||
_Terminal 2_ | ||
```bash | ||
sudo tc qdisc add dev docker0 root netem delay 20ms; | ||
sleep 10; | ||
sudo tc qdisc del dev docker0 root netem delay 20ms | ||
``` | ||
|
||
The output now shows that the application slowed down while waiting on sockets (lower TPS), many timeout errors, and that each of those timeouts resulted in a churned connection: | ||
|
||
``` | ||
Run time: 31.616 seconds | ||
Successful writes: 4991677 | ||
Connection errors: 0 | ||
Timeout errors: 8323 | ||
Max errors exceeded: 0 | ||
Node unavailable errors: 0 | ||
Other errors: 0 | ||
Connections opened: 8419 | ||
Connections closed: 8323 | ||
``` | ||
|
||
### Step 3 - Run with a 10 second period of latency with circuit breaker | ||
|
||
Perform 5 million write operations with `maxErrorRate=100` (default). __While the application is running__, add 20ms of latency to the Docker network interface, wait 10 seconds, then remove the latency: | ||
|
||
_Terminal 1_ | ||
```bash | ||
java -jar \ | ||
target/aerospike-circuit-breaker-java-1.0-SNAPSHOT-jar-with-dependencies.jar \ | ||
172.17.0.2:3000 100 5000000 | ||
``` | ||
|
||
_Terminal 2_ | ||
```bash | ||
sudo tc qdisc add dev docker0 root netem delay 20ms; | ||
sleep 10; | ||
sudo tc qdisc del dev docker0 root netem delay 20ms | ||
``` | ||
|
||
The output now shows that the application didn't slow down waiting on sockets (same or better TPS), timeout errors were capped and thus connections churned were capped. | ||
|
||
``` | ||
Run time: 16.205 seconds | ||
Successful writes: 1373172 | ||
Connection errors: 0 | ||
Timeout errors: 1428 | ||
Max errors exceeded: 3625400 | ||
Node unavailable errors: 0 | ||
Other errors: 0 | ||
Connections opened: 1524 | ||
Connections closed: 1428 | ||
``` | ||
|
||
In a real-world scenario, the exception handler for the `MAX_ERROR_RATE` would be able handle the back pressure according to the use case. For example, if the application is still within SLA and/or there isn't an end-user waiting on a response, the failed operations can be queued for a retry later when the network stabilizes. | ||
|
||
```java | ||
public void onFailure(AerospikeException e) { | ||
|
||
switch (e.getResultCode()) { | ||
// ... | ||
case ResultCode.MAX_ERROR_RATE: | ||
// Exceeded max number of errors per tend interval (~1s) | ||
// The operation can be queued for retry with something like | ||
// like an exponential backoff, captured in a dead letter | ||
// queue, etc. | ||
break; | ||
// ... | ||
} | ||
} | ||
|
||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# Aerospike database developer configuration file. | ||
|
||
service { | ||
proto-fd-max 1024 | ||
cluster-name example | ||
disable-udf-execution true | ||
} | ||
|
||
logging { | ||
console { | ||
context any info | ||
} | ||
} | ||
|
||
network { | ||
service { | ||
address any | ||
port 3000 | ||
} | ||
|
||
heartbeat { | ||
mode mesh | ||
port 3002 | ||
} | ||
|
||
fabric { | ||
port 3001 | ||
} | ||
} | ||
|
||
namespace testNamespace { | ||
replication-factor 1 | ||
|
||
storage-engine memory { | ||
data-size 1G | ||
} | ||
} |
Oops, something went wrong.