Skip to content

How AuthP handles sharding

Jon P Smith edited this page Aug 20, 2024 · 6 revisions

This document tells you how the AuthP's sharding feature works internally, updated to AuthP version 6 and above. You don't need to read this to create a sharding multi-tenant application, but knowing how sharding works inside might help you build a better app.

How the correct tenant's database is found

Once you add the SetupMultiTenantSharding method to the registering of the AuthP, then you are some from of sharding multi-tenant application. At this point (irrespective of whether its hybrid or sharding-only) accessing a tenant's data is a lot more complex over the default "all tenants share one database" approach.

The "all tenants share one database" approach uses a connection string that provides all the information to access a database. But a sharding multi-tenant app needs to creates a connection string by combining:

dynamically create a connection string to get the a) the correct database server, and b) the correct database on that database server. This creates the complete connection string by combining the two parts:

  1. The database server from a named "ConnectionStrings" in the appsettings file (See note later about using Azure databases)
  2. The database name from the sharding entries.

The the name of the connection string and the database name are supplied by an ShardingEntry which contains the following data.

Name What is contains
DatabaseName The name of the database
ConnectionName The name of the connection string defining the server
DatabaseType Short name of the database provider (e.g. SqlServer).
Used to select the correct connection string builder.
Name This is the unique key to this entry

An AuthP's Tenant using sharding has an properly that holds the Name of the ShardingEntry, which a tenant user (i.e. a AuthUser linked to a tenant) is linked to. When a tenant user logs in the Name of the ShardingEntry is turned into a claim (for performance reasons). The diagram below shows the four steps that are executed every time a tenant user makes a HTTP request.

ShardingSettingsSteps2

This might things this process will be slow, but in fact its very fast. That because each three lookups below each take less that 100 nanoseconds:

  1. Get sharding name from the user's claims - very fast.
  2. The sharding entries are handled by my Net.DistributedFileStoreCache, which takes about ~25 ns to an entry.
  3. Reading the connection string is fast too, maybe in the range ~25 ns.

How you form the final connection string?

To form the final connection string you need to use the correct connection string builder, and its done via various classes that implement the IDatabaseSpecificMethods interface. This interface has two key parts:

  1. A string property called DatabaseProviderShortName, which contains the key (e.g. "SqlServer")
  2. A method called FormShardingConnectionString which will use the connection string builder for the database provider defined by the DatabaseProviderShortName

This allows the code that needs the final connection string can select the correct IDatabaseSpecificMethods implementation for the database provider defined in the sharding entry.

There are built-in implementations:

And the SetupMultiTenantSharding extension method selects the correct implementation based on what database type you have selected.

Handling a custom database

If you want to use another database (see custom database feature), then you would:

  • Create an implementation of the IDatabaseSpecificMethods for your database type.
  • Copy the SetupMultiTenantSharding extension method and register your IDatabaseSpecificMethods instead of the built-in implementation.

Accessing the connection strings, including Azure

One of the jobs of the appsettings file is hold the connection strings to access the database(s) your application uses. These connection strings contain parts like username / password which must be kept secret. There are various ways to hide connection strings, such as ASP.NET Core secrets and have Azure can override your connection strings. Therefore the appsettings file is a great place to hold your connection strings.

AuthP in AddSharding mode the appsettings file holds the AuthP's database (which in hybrid mode can be used for shard tenants) via the "DefaultConnection" entry. If you want to provide extra connection strings they SHOULD NOT have a database name. That's because these connection strings are defining the server, with the database part updated later by the sharding process. The json below shows an example multiple connection strings linked to Azure databases.

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=tcp:CentralServer.database.windows.net,1433;Database=AuthPDatabase;User ID...",
    "WestCoastServer": "Server=tcp:WestCoastServer.database.windows.net,1433;User ID...",
    "CentralServer": "Server=tcp:CentralServer.database.windows.net,1433;User ID=...",
    "EastCoastServer": "Server=tcp:EastCoastServer.database.windows.net,1433;User ID=..."
  },
}

When using Azure you can override the connection strings via the App Service -> Configuration tab. This overrides any value the ConnectionStrings" section of the appsettings file - see this Azure document which shows how you can configure connections strings (NOTE: Its even easier by using Visual Studio's Publish feature).

IMPORTANT NOTE: Do NOT use Azure Key Vault provider if you have a high activity because it has a limit of 200 requests / second. Because each tenant user accessing the data has to read the connection string every time, which means if your have lots of simultaneous users that would slow down your application.

Additional resources

Articles / Videos

Concepts

Setup

Usage

Admin

SupportCode

Clone this wiki locally