Масштабируйте IdentityServer4 по регионам

В настоящее время я запускаю IDS4 как один экземпляр в одном регионе (единая база данных для конфигурации и оперативного хранилища). Теперь мне нужно распределить установку по двум регионам, чтобы службы/пользователи в регионе A имели доступ к IDS в регионе A, а службы/пользователи в регионе B имели доступ к IDS в регионе B.

Оба экземпляра должны обращаться к одному и тому же хранилищу данных, но IDS в регионе B не должны выполнять межрегиональные запросы на чтение к базе данных в регионе A.

Мы используем Azure SQL Server и функцию георепликации, которая предлагает один экземпляр с возможностью записи (в регионе A или B) и несколько экземпляров с возможностью чтения. Мы указали IDS в регионе B на доступный только для чтения экземпляр в том же регионе, но это не работает, поскольку IDS приходится записывать рабочие данные, такие как постоянные гранты.

Существует ли рекомендуемая архитектура для достижения этой цели, или у вас есть опыт реализации развертывания IDS в нескольких регионах и с балансировкой нагрузки? Можно ли настроить IDS для использования другой базы данных для операций записи и базы данных в том же регионе для операций чтения?

Добро пожаловать в СО. Пожалуйста, потратьте минуту, чтобы прочитать stackoverflow.com/help/как спросить

Bussller 27.02.2019 08:37
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
425
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Маловероятно, что вы найдете рекомендуемую архитектуру для подобного сценария из-за того, что большая часть этой проблемы связана с вашей бизнес-сферой. Кроме того, в библиотеке 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 Вы отметили это как принятый ответ, но прокомментировали ответ Альберто Морилло о том, что он сработал, используя его предложение. Поскольку у нас такая же проблема, мне было интересно, что вы в итоге сделали.

Jon Mitchell 16.10.2020 13:37

Вместо георепликации вы можете использовать Azure SQL Data Sync, чтобы иметь доступные для записи реплики базы данных SQL Azure, определяя одну из них как базу данных-концентратор, а другие — как базу данных-член. Синхронизация между всеми базами данных может быть двунаправленной, поэтому все базы данных могут обновляться. Вы можете начать настройку синхронизации данных SQL Azure в документации это.

Мы успешно настроили синхронизацию данных между двумя базами данных, и она работает нормально. В отличие от репликации данных георепликации Azure SQL почти в реальном времени, синхронизация данных реплицируется только каждые 5 минут. Мне интересно, может ли это привести к проблемным ситуациям. При нормальной работе пользователь всегда обращается к одному и тому же региону и, следовательно, к одной и той же базе данных. В случае отработки отказа в худшем случае пользователю придется повторно аутентифицироваться, поскольку сохраненное разрешение не было синхронизировано. Любые другие данные (например, данные конфигурации) будут синхронизированы после того, как регион снова станет доступным.

lunzi 28.02.2019 17:29

На частоте синхронизации вы можете выбрать секунды. «Если вы выберете «Вкл», введите число и выберите «Секунды», «Минуты», «Часы» или «Дни» в разделе «Частота синхронизации». Подробнее о настройке «Автоматическая синхронизация» читайте здесь. docs.microsoft.com/en-us/azure/sql-database/…

Alberto Morillo 28.02.2019 20:58

Я уже проверил документы, и там написано: Минимальная продолжительность между синхронизациями составляет пять минут.

lunzi 01.03.2019 09:18

Я нахожусь в процессе исправления ошибок в моей собственной частной вилке IdentityServer4.Contrib.CosmosDB. Если вы посмотрите на (очень незаконченный банкомат) исходный код, вы получите общее представление о том, как реализовать свой собственный поставщик БД, который изящно обрабатывает такое требование. На самом деле вы можете гипотетически подумать об использовании хранилища данных NoSQL для IDServer, поскольку я считаю, что оно «оптимизировано» для операций чтения/записи в нескольких регионах по сравнению с SQL Server.

Другие вопросы по теме