# How Bella OpenAPI Achieves High Throughput with Its Disruptor-Based Async Logging Framework

> Discover how Bella OpenAPI's Disruptor-based async logging framework achieves millions of events per second using a lock-free ring buffer and CAS operations. Learn about high-throughput logging.

- Repository: [Ke Technologies/bella-openapi](https://github.com/lianjiatech/bella-openapi)
- Tags: performance
- Published: 2026-03-06

---

**Bella OpenAPI leverages the LMAX Disruptor library to implement a lock-free, asynchronous logging pipeline capable of ingesting millions of events per second through CAS operations on a 1024-slot ring buffer.**

The Bella OpenAPI platform processes massive API request volumes requiring detailed cost tracking, metrics, and rate-limiting without impacting latency. According to the `lianjiatech/bella-openapi` source code, the Disruptor-based async logging framework achieves this by moving all heavy processing to a dedicated consumer thread while allowing producer threads to publish events via single atomic operations.

## Ring Buffer Architecture and Configuration

The foundation of the framework is a `Disruptor<LogEvent>` configured in [`BellaAutoConf.java`](https://github.com/lianjiatech/bella-openapi/blob/main/BellaAutoConf.java) (lines 82-84). This instantiation creates a 1024-slot ring buffer using `ProducerType.MULTI` to support concurrent publishers and a `SleepingWaitStrategy` for low-CPU wait cycles when the consumer awaits new events.

```java
// Configuration excerpt from BellaAutoConf.java
Disruptor<LogEvent> disruptor = new Disruptor<>(
    LogEvent::new,
    1024,  // Ring buffer size - power of 2 for efficient modulo
    DaemonThreadFactory.INSTANCE,
    ProducerType.MULTI,  // Multiple threads can publish concurrently
    new SleepingWaitStrategy()
);

```

The `ProducerType.MULTI` setting is critical for high throughput, as it enables lock-free publishing via compare-and-swap (CAS) operations rather than contending on mutex locks.

## Lock-Free Event Publication

Every request handler constructs a `LogEvent` containing `EndpointProcessData`, repository code, and a `costOnly` flag, then publishes it to the `logRingBuffer`. As implemented in [`LogEvent.java`](https://github.com/lianjiatech/bella-openapi/blob/main/LogEvent.java), the publication is a single atomic CAS operation that returns immediately, ensuring the request thread never blocks on I/O or computation.

```java
@Autowired
private RingBuffer<LogEvent> logRingBuffer;

public void recordLog(EndpointProcessData data, String repoCode, boolean costOnly) {
    // Single atomic operation - no locks, no blocking
    logRingBuffer.publishEvent((event, seq) -> {
        event.setData(data);
        event.setRepositoryCode(repoCode);
        event.setCostOnly(costOnly);
    });
}

```

This pattern ensures that logging latency on the critical path remains sub-microsecond, regardless of downstream processing complexity.

## The Handler Pipeline

The Disruptor wires a chain of **EventHandler** implementations that execute sequentially on a dedicated consumer thread. The pipeline processes each `LogEvent` through four specialized handlers:

- **CostLogHandler** — Calculates request cost and updates the in-memory `CostCounter`.
- **LogRecordHandler** — Persists raw log records into each configured `LogRepo`.
- **MetricsLogHandler** — Feeds data to the `MetricsManager` for real-time dashboards.
- **LimiterLogHandler** — Updates per-tenant rate-limit counters.

Each handler receives the same event instance in sequence, allowing the pipeline to remain modular while maintaining strict ordering guarantees. The consumer thread can also leverage the `endOfBatch` flag to combine database writes or metric pushes, reducing per-event overhead.

## Exception Isolation and Fault Tolerance

To prevent individual handler failures from stalling the entire pipeline, the framework registers a `LogExceptionHandler` as the default exception handler. This component ensures that any handler failure is logged but does **not** stall the ring buffer, preserving overall throughput under error conditions.

## Graceful Shutdown and Data Integrity

When the application container stops, `BellaAutoConf.shutdownDisruptors()` (lines 97-104) initiates an orderly shutdown sequence. This method signals the Disruptor to halt after processing all remaining events in the ring buffer and explicitly flushes the `CostCounter`, ensuring no log events or cost calculations are lost during deployment or restart operations.

## Key Throughput Optimizations

The Disruptor-based async logging framework achieves its high throughput through several coordinated mechanisms:

**Lock-Free Publishing** — The combination of `ProducerType.MULTI` and atomic CAS operations on the ring buffer allows any request thread to enqueue events without mutex contention or thread blocking.

**Cache-Friendly Memory Layout** — The circular array resides in a single contiguous memory region, enabling CPU prefetch and eliminating false sharing between producer and consumer threads.

**Separation of Concerns** — Heavy work including database writes, cost calculations, and metric updates executes exclusively on the consumer thread, keeping the request handler's critical path minimal.

**Batch Processing Capability** — Handlers receive events with an `endOfBatch` flag, enabling them to combine operations and reduce system call overhead.

**Low-Latency Waiting** — The `SleepingWaitStrategy` spins briefly then yields, providing fast wake-up times for the consumer thread without burning CPU cycles when idle.

**Modular Handler Design** — Adding or removing handlers does not require changes to other stages, maintaining pipeline predictability and allowing independent scaling of concerns.

## Summary

- Bella OpenAPI uses the **LMAX Disruptor** to build a lock-free logging pipeline that decouples event production from consumption.
- The **1024-slot ring buffer** with `ProducerType.MULTI` enables multi-threaded CAS publishing without blocking the request path.
- Four specialized **EventHandler** implementations process logs sequentially on a dedicated thread.
- **Exception isolation** via `LogExceptionHandler` prevents individual failures from crashing or stalling the pipeline.
- **Graceful shutdown** logic in `BellaAutoConf.shutdownDisruptors()` flushes pending events and cost counters to prevent data loss.

## Frequently Asked Questions

### What makes the Disruptor pattern faster than traditional queue-based logging?

The Disruptor eliminates locks and contention by using a circular array with atomic CAS operations for publishing, whereas traditional `BlockingQueue` implementations rely on locks and condition variables that create thread contention. Additionally, the ring buffer's contiguous memory layout improves CPU cache locality, reducing cache misses during high-throughput scenarios.

### How does Bella OpenAPI prevent log loss during application shutdown?

The `BellaAutoConf.shutdownDisruptors()` method coordinates an orderly shutdown by signaling the Disruptor to complete processing all events remaining in the ring buffer before terminating the consumer thread. This method also explicitly flushes the in-memory `CostCounter`, ensuring all cost calculations are persisted even during container restarts or deployments.

### Can multiple threads safely publish log events simultaneously without blocking?

Yes, the framework configures the Disruptor with `ProducerType.MULTI` in [`BellaAutoConf.java`](https://github.com/lianjiatech/bella-openapi/blob/main/BellaAutoConf.java), which implements a multi-producer lock-free algorithm using atomic operations on sequence counters. This allows any number of request handler threads to publish `LogEvent` instances concurrently without blocking or requiring explicit synchronization on the critical path.

### What happens if the database or metrics backend becomes slow or unavailable?

Because all persistence logic runs in the `LogRecordHandler` and `MetricsLogHandler` on a separate consumer thread, slow downstream operations do not block the request threads producing events. The `LogExceptionHandler` captures any persistence failures without halting the pipeline, while the ring buffer acts as a bounded buffer that absorbs temporary backpressure; if the buffer fills, producers will back off, but this occurs off the critical request path.