跨区域扩展 IdentityServer4
Scale IdentityServer4 across regions
我目前 运行 IDS4 作为一个区域中的单个实例(用于配置和操作存储的单个数据库)。我现在必须跨两个区域分发安装,以便区域 A 中的 services/users 访问区域 A 中的 IDS 和区域 B 中的 services/users 访问区域 B 中的 IDS。
两个实例应该访问相同的数据存储,但是区域 B 中的 IDS 不应该对区域 A 中的数据库进行跨区域读取查询。
我们使用 Azure SQL 服务器和地理复制功能,它提供单个可写实例(在区域 A 或 B 中)和多个可读实例。我们将区域 B 中的 IDS 指向同一区域中的只读实例,但这不起作用,因为 IDS 必须写入持久授权等操作数据。
是否有推荐的架构来实现此目的,或者您是否有实施多区域和负载均衡 IDS 部署的经验?是否可以将 IDS 配置为使用不同的数据库进行写入操作,并使用同一区域中的数据库进行读取操作?
由于您的业务领域中有多少此类问题,您不太可能会为此类场景找到推荐的架构。此外,Identity Server 4 库或其支持库中没有任何现成的东西可以满足您的标准。
话虽如此,我也有类似的要求(与 Identity Server 4 无关,但简而言之功能要求相同),应该可以根据您的情况采用相同的想法。
首先,你所说的唯一问题是,开箱即用,使用 Identity Server 4 EF 包,PersistedGrantStore
使用一个 IPersistedGrantDbContext
,它既写又写从数据库中读取。因此,为了解决这个问题,您基本上需要创建自己的 IPersistedGrantStore
实现,并且在该自定义实现中,您可以在技术上使用两种不同的 DbContext
类型,其中一种将使用连接字符串来创建数据库的单个可写实例,仅用于实现执行写入的接口方法,另一个仅用于读取方法,并将连接字符串用于数据库的只读实例。
以上总结的基本思路如下:
public class MyCustomPersistedGrantStore : IPersistedGrantStore
{
private readonly WriteOnlyPersistedGrantDbContext _writeContext;
private readonly ReadOnlyPersistedGrantDbContext _readContext;
public PersistedGrantStore(WriteOnlyPersistedGrantDbContext writeContext, ReadOnlyPersistedGrantDbContext readContext)
{
_writeContext = writeContext;
_readContext = readContext;
}
public Task StoreAsync(PersistedGrant token)
{
//Use _writeContext to implement storage logic
}
public Task<PersistedGrant> GetAsync(string key)
{
//Use _readContext to implement read logic
}
...other interface methods
}
实现自定义版本后,您需要做的就是将 IPersistedGrantStore
和 DbContext
的实现添加到 DI 系统中。
最后,值得注意的是,如果您停止使用 .AddOperationalStore(...config)
,那么您也会失去对 TokenCleanupHostService
的使用,因此您也需要实施它。
您可以使用 Azure SQL 数据同步来获取 Azure SQL 数据库的可写副本,而不是异地复制,将其中一个定义为中心数据库,将其他定义为成员数据库。所有数据库之间的同步可以双向配置,因此所有数据库都是可更新的。您可以在 this 文档中开始配置 Azure SQL 数据同步。
我正在解决我自己的 IdentityServer4.Contrib.CosmosDB 私人分支中的问题。如果您查看(非常未完成的 atm)源代码,您将大致了解如何实现您自己的 DB 提供程序以优雅地处理此类需求。实际上,您可能想假设地考虑为 IDServer 使用 NoSQL 数据存储,因为我认为与 SQL 服务器相比,多区域 reads/writes 是 'optimized'。
我目前 运行 IDS4 作为一个区域中的单个实例(用于配置和操作存储的单个数据库)。我现在必须跨两个区域分发安装,以便区域 A 中的 services/users 访问区域 A 中的 IDS 和区域 B 中的 services/users 访问区域 B 中的 IDS。
两个实例应该访问相同的数据存储,但是区域 B 中的 IDS 不应该对区域 A 中的数据库进行跨区域读取查询。
我们使用 Azure SQL 服务器和地理复制功能,它提供单个可写实例(在区域 A 或 B 中)和多个可读实例。我们将区域 B 中的 IDS 指向同一区域中的只读实例,但这不起作用,因为 IDS 必须写入持久授权等操作数据。
是否有推荐的架构来实现此目的,或者您是否有实施多区域和负载均衡 IDS 部署的经验?是否可以将 IDS 配置为使用不同的数据库进行写入操作,并使用同一区域中的数据库进行读取操作?
由于您的业务领域中有多少此类问题,您不太可能会为此类场景找到推荐的架构。此外,Identity Server 4 库或其支持库中没有任何现成的东西可以满足您的标准。
话虽如此,我也有类似的要求(与 Identity Server 4 无关,但简而言之功能要求相同),应该可以根据您的情况采用相同的想法。
首先,你所说的唯一问题是,开箱即用,使用 Identity Server 4 EF 包,PersistedGrantStore
使用一个 IPersistedGrantDbContext
,它既写又写从数据库中读取。因此,为了解决这个问题,您基本上需要创建自己的 IPersistedGrantStore
实现,并且在该自定义实现中,您可以在技术上使用两种不同的 DbContext
类型,其中一种将使用连接字符串来创建数据库的单个可写实例,仅用于实现执行写入的接口方法,另一个仅用于读取方法,并将连接字符串用于数据库的只读实例。
以上总结的基本思路如下:
public class MyCustomPersistedGrantStore : IPersistedGrantStore
{
private readonly WriteOnlyPersistedGrantDbContext _writeContext;
private readonly ReadOnlyPersistedGrantDbContext _readContext;
public PersistedGrantStore(WriteOnlyPersistedGrantDbContext writeContext, ReadOnlyPersistedGrantDbContext readContext)
{
_writeContext = writeContext;
_readContext = readContext;
}
public Task StoreAsync(PersistedGrant token)
{
//Use _writeContext to implement storage logic
}
public Task<PersistedGrant> GetAsync(string key)
{
//Use _readContext to implement read logic
}
...other interface methods
}
实现自定义版本后,您需要做的就是将 IPersistedGrantStore
和 DbContext
的实现添加到 DI 系统中。
最后,值得注意的是,如果您停止使用 .AddOperationalStore(...config)
,那么您也会失去对 TokenCleanupHostService
的使用,因此您也需要实施它。
您可以使用 Azure SQL 数据同步来获取 Azure SQL 数据库的可写副本,而不是异地复制,将其中一个定义为中心数据库,将其他定义为成员数据库。所有数据库之间的同步可以双向配置,因此所有数据库都是可更新的。您可以在 this 文档中开始配置 Azure SQL 数据同步。
我正在解决我自己的 IdentityServer4.Contrib.CosmosDB 私人分支中的问题。如果您查看(非常未完成的 atm)源代码,您将大致了解如何实现您自己的 DB 提供程序以优雅地处理此类需求。实际上,您可能想假设地考虑为 IDServer 使用 NoSQL 数据存储,因为我认为与 SQL 服务器相比,多区域 reads/writes 是 'optimized'。