Skip to content

Latest commit

 

History

History
278 lines (200 loc) · 12.4 KB

File metadata and controls

278 lines (200 loc) · 12.4 KB

Low-Latency Account Management System Over TCP and Shared Memory

An event-driven account management system utilising Chronicle libraries for high-performance and low-latency operations. This project demonstrates a reference architecture for creating accounts, performing transfers, and capturing checkpoints of system state, supported by comprehensive testing and benchmarking tools.

This project showcases a low-latency, high-performance account management microservice accessible via TCP or shared memory. Each inbound and outbound message is persisted in a Chronicle Queue, ensuring durability and traceability. The system is designed to produce minimal garbage and reduce latency jitter, making it suitable for high-frequency financial operations.

Built on Chronicle Queue and leveraging YAML-based input data, this service uses a fluent interface pattern to handle various account operations, such as account creation, fund transfers, and state checkpoints. It also includes benchmarking and testing utilities for performance evaluation.

Key Features

Low Latency

Designed for microsecond-level response times, especially when using shared memory transport.

High Throughput

Capable of handling high transaction volumes with minimal garbage production.

Fault Tolerance & Durability

All messages persist in a Chronicle Queue, aiding recovery and auditability.

Flexible Communication

Supports TCP and shared memory transport configurations.

Modular Design

Separates API, DTOs, and implementations for easier maintenance and extension.

System Overview

Core Operations

  1. Account Creation: Create new accounts with specified details (name, account ID, currency, initial balance, and optional overdraft).

  2. Fund Transfers: Transfer funds between accounts, validating currencies, balances, and overdrafts. Produces events indicating success or failure.

  3. Checkpointing: Emit a snapshot of all accounts' current state at a given time for auditing or recovery.

Architecture and Communication

The service can operate in various configurations:

TCP Client to TCP Service

Offers the most flexibility for distributed deployments, with typical latencies under 20 µs.

TCP Client to Shared Memory Service

Achieves better performance, typically ~10 µs latency.

Shared Memory Client and Service

This method achieves the lowest latency, around 1.5 µs for typical operations.

Chronicle Services' channels package and Chronicle Queue facilitate fast, low-overhead message passing. State changes are persistently recorded for replay or state restoration.

Architecture and Key Components

Overview

The system is composed of the following layers:

Input/Output Layer

Handles external requests (e.g., through Chronicle Channels) and emits responses/events.

Service Layer

Contains domain services (e.g., AccountService) that enforce business rules like account creation, validation, currency checks, and balance updates.

DTOs (Data Transfer Objects)

Represent business events such as CreateAccount, Transfer, OnTransfer, etc. DTOs are validated before processing to ensure data integrity.

Event-Driven Model

Uses Chronicle’s method readers/writers and queues to handle requests asynchronously and at low latency.

Benchmarking and Testing Tools

Includes JLBH for microsecond-level latency testing and YAML-driven scenario tests.

Key Classes

  • AccountManagerImpl: Orchestrates incoming events, delegating domain logic to AccountService and communicating results back via AccountManagerOut.

  • AccountService: Encapsulates the domain logic for account management (e.g., validating accounts, performing transfers).

  • DTO Classes (CreateAccount, Transfer, OnTransfer, etc.): Define the structure and validation rules for events.

  • BenchmarkMain Classes: Run performance tests and measure end-to-end latencies under various throughput settings.

A typical flow: 1. A request (e.g., createAccount) arrives via a Chronicle channel. 2. AccountManagerImpl receives the request, delegates validation and business logic to AccountService. 3. AccountService returns success or a failure reason. 4. AccountManagerImpl emits corresponding events (e.g., onCreateAccount or createAccountFailed).

Testability and Benchmarking

A suite of tests and benchmarks (e.g., AccountManagerBenchmarkMain) allows easy verification of correctness and performance. You can measure latency, throughput, and other key metrics to ensure the service meets performance goals.

Making It Production-Ready with Chronicle Services

To further enhance this solution for production environments, consider using Chronicle Services. Chronicle Services provides advanced features to ensure high availability, resilience, and smooth operations, including:

Failover Support

If the primary fails, the system automatically switches to a standby service instance, minimizing downtime.

Process Restarting

Automatically restart services after unexpected terminations or during scheduled maintenance windows.

Live Upgrades

Deploy updates without halting the entire system, allowing for rolling upgrades with minimal latency impact.

Idempotent Collections

Simplify restartable event processing by ensuring operations can be safely replayed without side effects.

Acknowledged Replication

Achieve high availability and real-time distribution across hosts, ensuring data consistency and durability.

Encryption

Protect sensitive transaction data with on-disk encryption.

Monitoring & Management

Gain insights into system performance and health, enabling proactive troubleshooting and optimization.

Integrating Chronicle Services allows your account management microservice to meet strict service-level agreements (SLAs), maintain continuous uptime, and adapt to evolving business and technical requirements.

Chronicle Services Diagram

Consider running the service on a server with:

Modern, Fast CPU

Ensure sufficient but not excessive CPU cores.

High-Performance Storage (NVMe)

Reduces jitter from IO operations.

Fast Memory

Memory-intensive operations benefit from faster RAM.

Small Heap Size

A modest heap (e.g., 2 GB) is sufficient since most data is off-heap.

Tuned Eden Space

A large Eden space can reduce GC frequency. For modest volumes, ~1 GB Eden size may suffice.

Network Layouts

The client and the service can be laid out in various ways without changing the code.

Table 1. Ballpark latencies running on a production quality server

Client Side

Service Side

Typical Latency

99%ile latency

TCP

TCP

20 µs

25 µs

TCP

Shared Memory

10 µs

13 µs

Shared Memory

Shared Memory

1.5 µs

3 µs

Example: TCP Client, TCP Service

This approach offers the most distributed option. The typical latencies are under 20 µs with the 99%ile latency not much higher.

sequenceDiagram
    autonumber

    participant Client as Client Application
    participant Gateway as Gateway<br/> (TCP <-> Shared Memory)
    participant Service as Service<br/> (Account Manager)

    Client->>Gateway: transfer (via TCP)
    Note over Client,Gateway: The request is persisted<br/>to a Chronicle Queue

    Gateway->>+Service: transfer (via TCP)
    Note right of Gateway: Gateway acts as a bridge<br/>and persists the message
    Note right of Service: Service processes the event<br/>(update balances, etc.)

    Service->>-Gateway: onTransfer (via TCP)
    Note over Service,Gateway: Response is persisted again<br/> for audit and recovery

    Gateway->>Client: onTransfer (via TCP)
    Note left of Gateway: Client receives<br/> the result of the operation
Loading

This can be benchmarked all-in-one with the command line properties -Durl=tcp://localhost:1248 -DserviceUrl=tcp://:1248 running AccountManagerBenchmarkMain

Example: TCP Client, Shared Memory Service

This approach offers the most distributed option. The typical latencies are around 10 µs with the 99%ile latency not much higher.

sequenceDiagram
    autonumber

    participant Client as Client Application
    participant Gateway as Gateway<br/>(TCP <-> Shared Memory)
    participant Service as Service<br/> (Account Manager)

    Client->>Gateway: transfer (via TCP)
    Note over Client,Gateway: The request is persisted<br/> to a Chronicle Queue on the Gateway.

    Gateway->>+Service: transfer (via Shared Memory)
    Note right of Gateway: Gateway provides low-latency<br/> shared memory messaging
    Note right of Service: Service processes the event<br/> (e.g., debit & credit accounts)

    Service->>-Gateway: onTransfer (via Shared Memory)
    Note over Service,Gateway: Response is persisted again<br/> for audit and recovery

    Gateway->>Client: onTransfer (via TCP)
    Note left of Gateway: Client receives the result<br/> of the transfer operation
Loading

This can be benchmarked all-in-one with the command line properties -Durl=tcp://:1248 running AccountManagerBenchmarkMain

Example: Shared Memory Client and Service

This approach offers the most distributed option. The typical latencies are under 2 µs with the 99%ile latency about double this.

sequenceDiagram
    autonumber

    participant Client as Client Application
    participant Queue as Queue<br/> (Shared Memory Channel)
    participant Service as Service<br/> (Account Manager)

    Client->>Queue: transfer (via Shared Memory)
    Note over Client,Queue: The transfer request is immediately<br/> persisted in a Chronicle Queue<br/> for audit and recovery.

    Queue->>+Service: transfer (via Shared Memory)
    Note right of Queue: The Service reads the request<br/> directly from the Queue.
    Note right of Service: The Service processes the event<br/> (e.g., adjust balances).

    Service->>-Queue: onTransfer (via Shared Memory)
    Note over Service,Queue: The response event is<br/> also persisted in the Queue.

    Queue->>Client: onTransfer (via Shared Memory)
    Note left of Queue: The Client reads the response,<br/> completing the round-trip<br/> with minimal latency.
Loading

This can be benchmarked all-in-one with the default command line properties running AccountManagerBenchmarkMain

Package Structure

We lay out our packages in the following manner

  • api – Input and output interfaces defining the service contract.

  • dto – Data Transfer Objects (POJOs) representing commands and events.

  • impl – The core implementation of the account management logic.

  • util – Utility classes for low-level operations and helpers.

For demos, we might include main classes; however, for a production system, we use a framework Chronicle Services to handle manageability, monitoring, restart and failover.

How to Run

  1. Compile the source files using your preferred Java compiler.

  2. AccountManagerServiceMain runs the end service responsible for holding the state and generating results of transactions .

  3. AccountManagerGatewayMain acts as a gateway listening for TCP connections and writing to/reading from the shared memory queue the microservices uses

  4. AccountManagerClientMain injects a few simple messages and waits for resulting events from the AccountManagerImpl

AccountManagerBenchmarkMain runs a JLBH benchmark to report on the latency distribution running on your machine.

Prerequisites

You need Java 8 or above installed on your machine to run this system.

Input Data Format

Input data is given in YAML format. Here’s an example of an account creation:

# Creating an account for Alice with 1000 EUR
createAccount: {
  sender: gw1,
  target: vault,
  sendingTime: 2023-01-20T10:00:00,
  name: alice,
  account: 101013,
  currency: EUR,
  balance: 1000
}

And an example of a transfer:

# Alice sends 10 EUR to Bob
transfer: {
  sender: gw2,
  target: vault,
  sendingTime: 2023-01-20T10:03:00,
  from: 101013,
  to: 101025,
  currency: EUR,
  amount: 10,
  reference: Dog food
}

Limitations and Future Work

This demo does not handle all edge cases and lacks a user-friendly interface. Future enhancements may include:

  • Improved error handling

  • Better user interfaces or REST/HTTP endpoints

  • More robust fault tolerance and recovery strategies, possibly leveraging Chronicle Services further