A newer version of this documentation is available.

View Latest

Reactive asynchronous clients

You can use non-blocking programming to better utilize application and network resources and gain overall higher I/O throughput.

Applications can take full advantage of the network by becoming asynchronous or non-blocking. The asynchronous model can increase network throughput and make better use of local CPU and memory resources.

Some Couchbase SDKs offer non-blocking extensions and APIs to interact with a Couchbase cluster.

Issues with synchronous (blocking) programming

Most modern applications are I/O bound, that is, they spend most of their time waiting for a server to respond to a given request. In traditional blocking applications, the entire application is blocked (suspended) until data arrives from the network.

If an application can parallelize its interaction with the network (for example, a data mining application which has multiple sources to analyze) it can run in less time because network resources are retrieved concurrently rather than in sequence.

To implement network concurrency, some applications employ multiple threads: each thread being responsible for retrieving a single resource. While this approach may work for a small number of concurrent network operations, it quickly becomes unscalable if the number of resources to retrieve are numerous. Threads may also add additional maintenance overhead, as applications must ensure access to shared application resources are properly guarded and synchronized and sequential in an otherwise concurrent workload.

The asynchronous (non-blocking) model

Asynchronous (or non-blocking, or reactive) programming is a model in which applications are designed to schedule a given network operation and continue when this operation is completed. The application may perform other tasks while it is waiting for network I/O.

A classic example of a reactive application is a GUI interface: the application is constructed with a main loop or an event loop that listens for input events (such as a button click, focus, or typing). The application installs handlers to react when a given event is received as a result of user input.

If the GUI application needs to request something from the network, it may do so synchronously, but this would mean that the application is suspended (and will appear unresponsive as it cannot react to UI event). If the request is done asynchronously, the UI will continue to function and a handler may be called when the operation completes. The handler can process the information received from the network, for example, to update the contents of a browser.

Reactive applications

Reactive applications are built around receiving events. An event is a notification that something has happened; this can be the receipt of a network transmission or access of a UI element.

Events are generated by a component called a reactor or event loop. This component is responsible for delivering low-level events as generated by the network or operating system and delivering them to your application. Your application code is invoked by the reactor, and when your application code exits (for example, a function returns), control is given to the event loop so that it may continue processing events.

An application must ensure that it does not block waiting for network I/O: When application code blocks waiting for the network, the entire process (or thread) is blocked, and the reactor is not able to deliver events which may be ready. As such, any network I/O must be done via the reactor.

Using the reactive model with Couchbase

Some Couchbase SDKs allow a reactive model in which applications may use this form of parallelism with Couchbase operations: Applications can schedule operations to be performed, and then supply those operations with handlers to be invoked when the operation is complete.

An asynchronous application must be entirely non-blocking. This means that all components which interact with the network need to participate in the event loop or reactor. For example, if your application is also a web server, the web server must also receive requests and serve responses via the reactor. Most reactors feature built-in or third-party web servers and other forms of network service handlers and libraries.

There are various asynchronous frameworks for different languages. Consult your SDK documentation to see available options for integration with a given framework.

When to use the asynchronous/reactive model

Asynchronous models are generally recommended for high-throughput, high volume applications. The asynchronous model is capable of handling several thousand concurrent I/O operations in a single thread.

If your application is itself a server, and in addition to interacting with Couchbase, can also concurrently interact with other services, it is recommended to use the asynchronous programming model to greatly improve network throughput and conserve system resources.

When to use the synchronous/blocking model

Not all applications are suited for the asynchronous model. The asynchronous model introduces additional complexity in initial development and maintenance. Logically sequential logic may be fragmented into multiple functions because some steps require waiting for the network; and thus a function might need to be split into several parts—each interaction with the network requiring a different invocation as a handler.

When application parallelism is at a small scale, and when different network operations are not related and do not require shared state, the use of multiple threads or processes may be acceptable.