В настоящее время я запускаю IDS4 как один экземпляр в одном регионе (единая база данных для конфигурации и оперативного хранилища). Теперь мне нужно распределить установку по двум регионам, чтобы службы/пользователи в регионе A имели доступ к IDS в регионе A, а службы/пользователи в регионе B имели доступ к IDS в регионе B.
Оба экземпляра должны обращаться к одному и тому же хранилищу данных, но IDS в регионе B не должны выполнять межрегиональные запросы на чтение к базе данных в регионе A.
Мы используем Azure SQL Server и функцию георепликации, которая предлагает один экземпляр с возможностью записи (в регионе A или B) и несколько экземпляров с возможностью чтения. Мы указали IDS в регионе B на доступный только для чтения экземпляр в том же регионе, но это не работает, поскольку 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, поэтому вам также нужно будет реализовать это.
@lunzi Вы отметили это как принятый ответ, но прокомментировали ответ Альберто Морилло о том, что он сработал, используя его предложение. Поскольку у нас такая же проблема, мне было интересно, что вы в итоге сделали.
Вместо георепликации вы можете использовать Azure SQL Data Sync, чтобы иметь доступные для записи реплики базы данных SQL Azure, определяя одну из них как базу данных-концентратор, а другие — как базу данных-член. Синхронизация между всеми базами данных может быть двунаправленной, поэтому все базы данных могут обновляться. Вы можете начать настройку синхронизации данных SQL Azure в документации это.
Мы успешно настроили синхронизацию данных между двумя базами данных, и она работает нормально. В отличие от репликации данных георепликации Azure SQL почти в реальном времени, синхронизация данных реплицируется только каждые 5 минут. Мне интересно, может ли это привести к проблемным ситуациям. При нормальной работе пользователь всегда обращается к одному и тому же региону и, следовательно, к одной и той же базе данных. В случае отработки отказа в худшем случае пользователю придется повторно аутентифицироваться, поскольку сохраненное разрешение не было синхронизировано. Любые другие данные (например, данные конфигурации) будут синхронизированы после того, как регион снова станет доступным.
На частоте синхронизации вы можете выбрать секунды. «Если вы выберете «Вкл», введите число и выберите «Секунды», «Минуты», «Часы» или «Дни» в разделе «Частота синхронизации». Подробнее о настройке «Автоматическая синхронизация» читайте здесь. docs.microsoft.com/en-us/azure/sql-database/…
Я уже проверил документы, и там написано: Минимальная продолжительность между синхронизациями составляет пять минут.
Я нахожусь в процессе исправления ошибок в моей собственной частной вилке IdentityServer4.Contrib.CosmosDB. Если вы посмотрите на (очень незаконченный банкомат) исходный код, вы получите общее представление о том, как реализовать свой собственный поставщик БД, который изящно обрабатывает такое требование. На самом деле вы можете гипотетически подумать об использовании хранилища данных NoSQL для IDServer, поскольку я считаю, что оно «оптимизировано» для операций чтения/записи в нескольких регионах по сравнению с SQL Server.
Добро пожаловать в СО. Пожалуйста, потратьте минуту, чтобы прочитать stackoverflow.com/help/как спросить