Проблема с одновременным доступом к коллекции Global Dictionary в WebApi - PullRequest
0 голосов
/ 27 марта 2020

Тип проекта, о котором идет речь, - это WebApi, который предназначен для использования в качестве внутреннего компонента мультитенантной среды. WebApi предназначен для приема запросов от многих пользователей. Инициированные и отправленные запросы на стороне сервера являются как частыми, так и параллельными.

Более или менее, моя проблема вращается вокруг класса, который существует во внешнем проекте. Этот класс является основой всей системы, и он очень сложный; он содержит различные свойства stati c и методы stati c, которые WebAPI использует для взаимодействия с базами данных арендаторов, а также для достижения сложных функций. Причина, по которой мы используем внешний класс, заключается в том, чтобы просто иметь возможность повторно использовать функциональные возможности этого внешнего проекта без переписывания и повторного изобретения колеса.

Давайте назовем этот внешний класс - SMW. Допустим, у нас есть глобально определенный словарь stati c в WebApi.

Доступ к WebApi осуществляется различными пользователями из разных арендаторов. Когда пользователь из определенного арендатора обращается к любому из методов API, для этого арендатора инициализируется новый экземпляр SMW; затем выполняются некоторые методы для загрузки клиента на основе структур данных (в основном, stati c DataTables) и свойств stati c. По завершении экземпляр загружается в словарь на основе TenantID в качестве ключа. (идентификатор клиента всегда шифруется и передается в заголовке запроса Http)

Когда один и тот же пользователь (или другой пользователь) из того же арендатора снова получает доступ к любому из методов API, когда SMW уже загружен в словарь, вместо перезагрузки нового экземпляра, TenantID используется для извлечения соответствующего экземпляра SMW из памяти. На этом этапе некоторые методы могут (или не могут) быть переоценены для получения последних данных из базы данных.

Идея отлично работает, когда загружен один арендатор. Он также отлично работает, когда два арендатора загружены, учитывая, что запросы не совпадают. Всякий раз, когда к методам API обращаются пользователи из нескольких арендаторов одновременно, начинаются проблемы. В неизвестном месте словарь запутался.

Допустим, 2 пользователя, 1 из арендатора A и 1 из арендатора B, начинают инициировать запросы одновременно. Предполагается, что в словаре будет 2 записи, с экземпляром SMW в качестве «значения» и TenantID в качестве «ключа». При возникновении проблемы в словаре по-прежнему будет 2 ключа, но значение экземпляра SMW будет одинаковым для обоих арендаторов. Например, пользователи из арендатора A начнут видеть данные арендатора B, в то время как пользователи из арендатора B будут продолжать просматривать свои собственные данные, как и предполагалось.

В реальной реализации я всегда начинаю с проверки, содержит ли словарь ключ для данного арендатора, если это так, я создаю новый экземпляр класса и блокирую фактический элемент в словаре. Если в это время поступит другой запрос, я задерживаюсь до тех пор, пока экземпляр SMW не будет снова сохранен в словаре. В этот момент экземпляр освобождается (разблокируется), и дальнейшие запросы могут продолжаться.

Я также пытался использовать ConcurrentDictionary вместо словаря, чтобы попытаться достичь безопасности потока, но те же отрицательные результаты были достигнуты.

Я не могу точно определить, где Словарь запутался. Я попытался отладить, но я ограничен отладкой по одному процессу за раз, и один процесс всегда работает! Сейчас я продолжаю практически регистрировать все, что могу, и анализировать результаты. Определенно было бы трудно показать примеры кода в этом случае, но предложения любых эффективных методов устранения неполадок или даже областей, в которые нужно обратить особое внимание, приветствуются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...