Configuration

Many applications will only ever need to configure Spanner in terms of the database to connect via the connection string. (The database name consists of a project ID, instance ID and database ID.)

Beyond that, configuration is largely for the sake of diagnostics and performance tuning. There are two main sources for configuration:

  • The connection string provided to SpannerConnection. Options here are also exposed as properties on SpannerConnectionStringBuilder
  • The session pool options, as exposed via Google.Cloud.Spanner.V1.SessionPoolOptions.

The connection string options are specified in this document. The remaining options relate to the session pool, which handles acquiring, refreshing and evicting sessions. Spanner sessions are relatively expensive (in terms of time) to create, so it's important that they are handled appropriately.

Session pool options explained

SessionPoolOptions exposes the following properties:

MaximumActiveSessions

Default value: 400

The maximum number of sessions that can be active per database. An active session is one that has been acquired but not yet released back to the pool. Broadly speaking, this is equivalent to the number of concurrent Spanner-based operations your application will be able to perform.

Applications may wish to change this setting if they require high levels of concurrency.

MinimumPooledSessions

Default value: 100

The minimum number of sessions to maintain in the pool of available sessions, on a per-database basis. If the number of pooled sessions falls below this number, more sessions are added automatically, unless that would require more than the configured maximum active session count. (Setting the minimum pool size to a larger value than the maximum active session count has no purpose; the size will still be bounded by the maximum active session count.)

Applications may wish to change this setting if they are likely to encounter sudden bursts of requests, and don't wish to have to wait for sessions to be created.

WriteSessionsFraction

Default value: 0.2

The session pool maintains sessions in two states:

  • Without a transaction
  • With a read/write transaction

The value of this setting determines how many sessions to keep in each state. For example, with the default value of 0.2, roughly 20% of sessions will be pooled with a read/write transaction.

When a session is acquired, if there is not one already available with the requested transaction options, a transaction can be requested. Using a session which was previously associated with a read/write transaction for operations which don't use that transaction does not affect the behavior; it just wastes the small amount of time spent creating the transaction to start with.

Increasing this value will increase the average time taken to release a session back to the pool, as more read/write transactions will be acquired as part of that operation. However, acquiring sessions with read/write transactions from the pool will then be faster.

Applications that are aware of their usage patterns ahead of time may wish to change this setting to reduce latency. This is particularly true for applications which only perform read-only operations (in which case this value should be set to 0) or only perform operations using read/write transactions (in which case this value should be set to 1.0).

IdleSessionRefreshDelay

Default value: 15 minutes

After this amount of time, a session which has been idle is refreshed automatically.

Sessions that are unused for long periods of time can be invalidated by the server. The session pool periodically checks whether pooled sessions need refreshing. When a session needs refreshing, the pool just executes a simple query using that session. Sessions are additionally checked for refresh when they are released back to the pool. Jitter is applied to the session refresh to avoid large numbers of sessions all being refreshed at exactly the same time.

Applications rarely need to change this setting.

PoolEvictionDelay

Default value: 7 days

Processes that run for extended periods may refresh sessions many times, and the server will generally permit this indefinitely. However, that puts a strain on server-side resource management. This setting controls the time after which sessions are evicted. Like refresh settings, jitter is applied so that sessions are not evicted all at once.

Applications rarely need to change this setting.

WaitOnResourcesExhausted

Default value: Block

This enum value controls the behavior when an application requests a new session despite having already acquired the maximum number of active sessions.

The default value (Block) will block the pending session acquisition operation until a session is available. This allows an application to continue to function correctly, but with reduced responsiveness.

The value of Fail will cause the pending session acquisition to throw an exception. This is useful for spotting resource leaks, and some applications may prefer a swift failure over a delayed response when the application is heavily loaded.

Timeout

Default value: 60 seconds

The total time allowed for a network call to the Cloud Spanner server, including retries. This setting is applied to calls to create, refresh and delete sessions, as well as beginning transactions.

Applications rarely need to change this setting.

CreateSessionMaximumBatchSize

Default value: 5

Sessions created are associated to the gRPC channel they are created on, so all sessions created in a batch are associated to the same gRPC channel. Batch size should be limited so as not to overload a given channel. If the sessions needing to be created at any given time are more than this value then multiple batches of this size or less will be created.

Applications rarely need to change this setting.

MaximumConcurrentSessionCreates

Default value: 50

Spanner has limits on the number of sessions that can be created concurrently without affecting performance. The session pool uses this setting to throttle the number of concurrent sessions batch creation operations, across all databases.

Applications rarely need to change this setting.

SessionLabels

Default value: empty

SessionLabels is a read-only property which returns a mutable string-to-string dictionary.

When sessions are created, they can have key/value pairs as labels. These can be used diagnostically. For example, if your applicaiton contains a number of services, each service could use a different value for a "service" label so you could tell which services are creating how many sessions. You could additionally have a separate "service-instance" label for each instance of the service.

Modifying the default SessionPoolOptions from ADO.NET

When using the ADO.NET implementation (Google.Cloud.Spanner.Data), a SessionPoolManager is used to create SessionPool instances based on the connection string. (Different endpoints would require different pools, for example.) Each SessionPoolManager has a set of SessionPoolOptions that it uses whenever it creates a new SessionPool. It's easy to modify the options used by the default SessionPoolManager. For example, to change the minimum number of sessions in each session pool:

SessionPoolManager.Default.SessionOptions.MinimumPooledSessions = 100;

Any changes to the options should be made before the first Spanner operation is executed. Changes to the options used by a SessionPool after it has become active may still take effect, but that varies by option and may change over time as an implementation detail.

Using a non-default SessionPoolManager

An alternative to modifying the options used by the default SessionPoolManager is to create a new manager object with a new set of options. The SessionPoolManager can then be set in SpannerConnectionStringBuilder which is then used to build a SpannerConnection. For example:

SessionPoolOptions options = new SessionPoolOptions
{
    MinimumPooledSessions = 100,
    MaximumActiveSessions = 250,
    SessionLabels =
    {
        { "service", "sales-report-generator" },
        { "service-instance", instanceId }
    }
};
SessionPoolManager manager = SessionPoolManager.Create(options);

// Note: a single SpannerConnectionStringBuilder instance can be reused whenever you
// need to build a connection
SpannerConnectionStringBuilder builder = new SpannerConnectionStringBuilder(connectionString)
{
    SessionPoolManager = manager
};

// (Elsewhere in your code...)
using (SpannerConnection connection = new SpannerConnection(builder))
{
    // Use the connection
}