Managing Connections Using the C (libcouchbase) SDK with Couchbase Server

This section describes how to connect the C SDK to a Couchbase cluster and bucket. It contains best practices as well as information on the connection string, SSL and other advanced connection options.

RBAC and the SDK

Couchbase Server 5.0 Enterprise Edition introduced Authorization. In order to access cluster-resources, programs, including those supported by the Couchbase SDK, must authenticate with Couchbase Server, and so be identified as existing users, each associated with one or more roles. Authentication requires the passing of credentials; which consist of a username and (in most cases) a password. Users may be defined either locally to Couchbase Server, or externally (for example, by means of an LDAP server).

Once authentication has succeeded, an authorization process checks the roles associated with the identified user. If role-associated privileges correspond to the level of resource-access requested by the user, access is duly granted; otherwise, it is denied.

Creating a handle

A library handle is created using the lcb_create() function which accepts an out-pointer to a handle and a parameters structure specifying some core options.

lcb_t instance = NULL;
lcb_create_st options;
memset(&options, 0, sizeof options);
options.version = 3;
options.v.v3.connstr = "couchbase://10.3.53.2/my-bucket";
options.v.v3.username = "jo";
options.v.v3.passwd = "s3cr3t";
lcb_error_t rc = lcb_create(&instance, &options);
if (rc != LCB_SUCCESS) {
    printf("Couldn't create handle: %s\n", lcb_strerror(NULL, rc));
}

You can specify additional options when connecting to the cluster by using the connection string. It indicates to the client where cluster nodes may be found and how to connect to them. Note that it is common to other Couchbase SDKs as well as the command-line client. The connection string uses a URI-like format familiar to what is used in other database systems.

From Couchbase C SDK 2.9.1, AlternateAddress is implemented, for connecting to nodes in a NATed environment, such as Docker containers using portmapping. It is on by default, if the server provides a topology that includes a multi-network configuration. Whichever network is selected at bootstrap will be logged. Alternately, choose your network using the connection string:

?network=NAME

If using Docker Swarm, or otherwise running the SDK inside the NAT, then you will want to disable with ?network=default in the connection string, or an environmental setting can be made.

The default network is not the same thing as default behavior; default behavior is to compare the hostname/port used to fetch the configuration against the internal address, and if it matches, should use the internal information - and otherwise to choose the external alternate names if available.

Note that any SSL/TLS certificates must be set up at the point where the connections are being made. The Couchbase SDKs will honor any valid SSL/TLS certificates.

Because the C SDK is used as a foundation for other SDKs, it allows for a common connection specification over all those other SDKs.

See Client Settings for the C (libcouchbase) SDK with Couchbase Server, which contains some additional connection string options.

When creating a new handle, you can also specify an alternate event loop plugin to use. This is required if you want to use your library in non-blocking mode with your existing non-blocking application.

Once your handle has been instantiated you may configure it additionally using the lcb_cntl() family of functions.

Note that a successful lcb_create invocation does not mean the handle has been connected to the bucket, but rather that memory has been allocated for the handle so that it may be connected in subsequent calls.

Connecting a handle

Once a handle has been instantiated it should be connected. Connecting a handle involves performing the following steps:

  1. Calling lcb_connect to schedule the connection.

  2. Yielding to network I/O, either explicitly via lcb_wait or implicitly by returning control to the event loop

  3. Retrieving the connection status via lcb_get_bootstrap_status. If running in non-blocking mode, installing the bootstrap callback (lcb_get_bootstrap_callback) should have a similar effect

    lcb_error_t rc;
    rc = lcb_connect(instance);
    if (rc != LCB_SUCCESS) {
        /* Couldn't schedule connection. Internal issue or problem with the socket */
        printf("Couldn't schedule bootstrap!: %s\n", lcb_strerror(NULL, rc));
        lcb_destroy(instance);
    }
    lcb_wait(instance);
    rc = lcb_get_bootstrap_status(instance);
    if (rc != LCB_SUCCESS) {
        printf("Bootstrapping failed: %s\n", lcb_strerror(NULL, rc));
        lcb_destroy(instance);
    }

Always check the return value of lcb_get_bootstrap_status to ensure the handle is properly connected. Performing operations on a non-bootstrapped handle will fail with LCB_CLIENT_ETMPFAIL.

Handle lifetime

The lcb_t object (commonly referred to as instance) represents a connection between your application and a Couchbase bucket. Because the bucket itself may consist of several TCP connections, and because there is a substantial amount of CPU and kernel overhead in creating and destroying these connections, it is recommended that lcb_t objects be kept alive for the lifetime of the application rather than creating and destroying them frequently.

Once the lcb_t is no longer required, you can call lcb_destroy() on it. The handle should not be destroyed within a callback as it will likely cause it to crash. Additionally, memory leaks may occur if there are pending uncompleted operations (e.g. lcb_get3, lcb_store3).

Configuring the handle

Once the handle is created, it may be configured by the lcb_cntl and lcb_cntl_string functions.

Connecting with SSL

You can specify additional options when connecting to the cluster by using the connection string. It indicates to the client where cluster nodes may be found and how to connect to them. Note that it is common to other Couchbase SDKs as well as the command-line client. The connection string uses a URI-like format familiar to what is used in other database systems.

Couchbase Sever features the ability to have clients communicate securely via SSL.

To use SSL, you need Couchbase Server Enterprise 3.0 or later (not available in the Community Edition).

  1. Obtain the SSL certificate used by the Cluster

  2. Make the certificate available to the file system of the client host.

  3. Employ the couchbases:// scheme for the connection string.

  4. Specify the local path to the certificate as the value for the certpath field.

To connect to a bucket on an SSL-enabled Cluster at the node 10.3.4.33, with the certificate saved as /var/cbcert.pem:

couchbases://10.3.4.33?certpath=/var/cbcert.pem

Specifying Multiple Hosts

You can specify multiple hosts in the connection string so that the client may be able to connect even if the cluster topology changed. To specify multiple hosts, separate them using a comma:

couchbase://host1.com,host2.com,host3.com

See Failure Considerations for the C (libcouchbase) SDK in Couchbase for more information about handling cluster topology changes.

You are not required to enumerate or pass all Couchbase cluster nodes to the client. The client only needs to know about a single node which is a member of the cluster. Once the client has connected to the node, it will query that node about the cluster topology, which in turn contains information about all Couchbase nodes and the services they contain.

Using DNS SRV records

As an alternative to specifying multiple hosts in your program, you can get the actual bootstrap node list from a DNS SRV record. The following steps are necessary to make it work:

  1. Set up your DNS server to respond properly from a DNS SRV request.

  2. Enable it on the SDK and point it towards the DNS SRV entry.

Your DNS server should be set up like this (one row for each bootstrap node):

_couchbase._tcp.example.com.  3600  IN  SRV  0  0  0  node1.example.com.
_couchbase._tcp.example.com.  3600  IN  SRV  0  0  0  node2.example.com.
_couchbase._tcp.example.com.  3600  IN  SRV  0  0  0  node3.example.com.
The ordering, priorities, ports and weighting are completely ignored and should not be set on the records to avoid ambiguities.

If you plan to use secure connections, you use _couchbases instead:

_couchbases._tcp.example.com.  3600  IN  SRV  0  0  0  node1.example.com.
_couchbases._tcp.example.com.  3600  IN  SRV  0  0  0  node2.example.com.
_couchbases._tcp.example.com.  3600  IN  SRV  0  0  0  node3.example.com.

In the above example, you would specify couchbase://example.com as the bootstrap host, and the library would check for the record. If no such record exists, it will treat example.com as an ordinary bootstrap node and try to bootstrap from it. Note that if you pass more than one bootstrap host, DNS SRV lookup will not be attempted, and the hosts will be interepreted as normal Couchbase nodes.

Configuration Cache

In environments when lots of short-lived connections are made to Couchbase (for example, a small command-line utility or a fork-and-execute CGI application) the overhead in actually bootstrapping the client may be significant. This is because the client must retrieve the configuration from the cluster, and involves several additional TCP requests and in many cases an additional TCP connection.

You can bypass the initial network bootstrap phase by using the config_cache directive in the connection string. The config_cache option accepts a path to a local file (the file should not exist when using for the first time). When performing the bootstrap process, the client will first check the contents of the given file to see if it contains an existing cluster configuration, and if it does, will use the file as the bootstrap source. If the file does not contain a configuration the client will then retrieve the configuration from the network and then write it to the file, so that future attempts will use the configuration file.

The config_cache feature is intended only for short-lived connections. During a cluster-side topology change the client will need to retrieve the configuration from the network as the file-based configuration will become invalid.

Additional Options

You can pass additional options in the connection string using the URL query format: couchbase://location-info?option1=value1&option2=value2&optionN=valueN. A list of options may be found in Client Settings