Skip to main content
adaptive distributed systems intent-based dynamic consistency in java 21

Verifying Adaptive Behavior

2 min read Chapter 25 of 25
Summary

Adaptive behavior verification in distributed systems using Toxiproxy...

Adaptive behavior verification in distributed systems using Toxiproxy and Testcontainers

Verifying Adaptive Behavior

Introduction

Adaptive behavior in distributed systems is crucial for maintaining performance and availability under various conditions. This section delves into the verification of adaptive behavior, focusing on strategy switching under load and fault conditions. We will explore how Toxiproxy and Testcontainers enable comprehensive chaos testing, ensuring distributed systems’ resilience.

Background

Distributed systems face numerous challenges, including network partitions, latency, and faults. To mitigate these issues, systems employ adaptive behavior, switching between strategies to maintain performance and availability. Linearizable consistency, deferred execution, and last-write-wins (LWW) conflict resolution are essential concepts in this context.

Adaptive Behavior Verification

Verification of adaptive behavior involves testing the system’s ability to switch strategies under load and fault conditions. This can be achieved using Toxiproxy and Testcontainers, which provide a robust framework for chaos testing. The following test cases demonstrate the verification of adaptive behavior:

Test Case 1: Latency-Induced Strategy Switching

public class AdaptiveBehaviorTest {
    @Test
    void doubleLatency_ShouldSwitchToDeferred() {
        var proxy = container.getProxy("database", 5432);
        proxy.toxics().latency("db-lag", ToxicDirection.DOWNSTREAM, 600);

        ExecutionResult result = evaluator.evaluate(highCriticalityIntent);
        
        assertThat(result.strategy()).isEqualTo(Strategy.ASYNC);
        assertThat(result.httpStatus()).isEqualTo(HttpStatus.ACCEPTED);
    }
}

This test case verifies that the system switches to the deferred execution strategy when latency exceeds 500ms.

Test Case 2: Partition-Induced Strategy Switching

public class AdaptiveBehaviorTest {
    @Test
    void healPartition_ShouldReturnToLinearizable() {
        var toxic = container.getProxy("database", 5432).toxics().bandwidth("cut", ToxicDirection.DOWNSTREAM, 0);
        verify(evaluator).strategy(Strategy.ASYNC);

        toxic.remove();

        ExecutionResult result = evaluator.evaluate(highCriticalityIntent);
        assertThat(result.strategy()).isEqualTo(Strategy.SYNC);
        assertThat(result.consistencyLevel()).isEqualTo(Consistency.LINEARIZABLE);
    }
}

This test case verifies that the system returns to linearizable consistency after a network partition is healed.

Decision Matrix

The following decision matrix outlines the expected behavior of the system under various conditions:

Health MetricIntent CriticalityTarget StrategyExpected Status
Latency < 500msHighSYNC / Linearizable200 OK
Latency > 500msHighASYNC / Deferred202 Accepted
Partition ActiveLowASYNC / Deferred202 Accepted
Partition HealedHighSYNC / Linearizable200 OK

Conclusion

In conclusion, verifying adaptive behavior in distributed systems is crucial for ensuring performance and availability under various conditions. By using Toxiproxy and Testcontainers, developers can create comprehensive chaos tests to verify the system’s ability to switch strategies under load and fault conditions.

Sources

[1] Toxiproxy Documentation [2] Testcontainers Documentation