В ASP.NET нормально ли хранить пользовательские данные в профиле с механизмом кэширования, а не в сеансе? - PullRequest
1 голос
/ 18 ноября 2009

Я несколько дней читал статьи об управлении состоянием в ASP.NET для своего веб-приложения. В этом приложении один пользователь может создавать / сохранять / выполнять запросы, и мне нужно сохранить каждый параметр запроса, прежде чем пользователь сможет сохранить запрос.
Эти параметры являются строковыми значениями, но глобальный размер для одного пользователя может превышать несколько мегабайт. Мы планируем, что наш сайт будет работать с ~ 100 пользователями одновременно.

В этих условиях я считаю, что нехорошо хранить эти значения в режиме сеанса в режиме in-proc.

Мы уже реализовали ProfileProvider: SqlProfileProvider, используя механизм кэширования и с AutoSave = true.

Какое лучшее решение: хранить эти значения в профиле или в сеансе, но в базе данных SQL?

Ответы [ 4 ]

1 голос
/ 18 ноября 2009

Лучшее решение зависит от того, планируете ли вы выйти за пределы одного сервера. В конфигурации с балансировкой нагрузки состояние сеанса InProc не будет работать правильно (без использования закрепленных сеансов, что создает другие проблемы). Вне состояния сеанса proc, такого как State Server или SQL Server, требуется, чтобы информация о вашем состоянии была сериализована и десериализована для каждого доступа к странице. С несколькими МБ на пользователя это может быть очень медленным.

Кэширование - это еще один вариант, предложенный Дейвом. Одной из проблем может быть необходимость синхронизации кэша с одного веб-сервера на другой.

Обычный подход к решению проблемы такого рода заключается в том, чтобы хранить данные в БД и в кэше и извлекать их только для тех страниц, где они действительно необходимы (в отличие от сеанса, который читается для каждой страницы). Затем используйте SqlDependency или SqlCacheDependency для кэширования данных таким образом, чтобы их можно было обновлять на нескольких серверах в случае изменения БД.

1 голос
/ 18 ноября 2009

1) Сессию можно хранить как Out Of Proc (на SQL Server), поэтому вопрос больше в том, где их хранить: в памяти или в базе данных. Если вы сохраните в памяти, он будет уничтожен автоматически. Если вы храните в базе данных, то вы можете использовать эти данные в течение сеансов. Решите, нужно ли вам сохранять эти параметры между сеансами (пользователь может переключать компьютеры; пользователь может время от времени открывать ваше приложение) - нужны ли ему эти параметры для него?

2) Подумайте об оптимизации - несколько мегабайт параметров на пользователя?!? Если это означает, что пользователь может иметь сотни запросов и они должны быть доступны при следующем входе пользователя в систему, сохраните все это в базе данных.

1 голос
/ 18 ноября 2009

Мы достигли определенного уровня успеха, сохранив информацию о пользователе на диск, чтобы сохранить ее в памяти. Когда вы хотите что-то конкретное, вам нужно прочитать его обратно в память, и это может быть немного медленно, но это работает.

Например, вы можете сериализовать некоторые объекты и записать их в файлы на жестком диске веб-сервера. Назовите файлы в соответствии с идентификатором сеанса, именем пользователя и т. Д., И затем вы сможете читать / записывать из / в файлы по мере необходимости.

1 голос
/ 18 ноября 2009

Зависит от памяти вашего сервера и от того, насколько вы обеспокоены этим. База данных всегда хороша для такого рода вещей, потому что у вас есть лучший параллелизм и более стабильный способ хранения ваших данных.

Я рекомендую вам использовать скользящий срок действия для кэшированных данных, скажем, 10-20 минут или около того. Таким образом, вы не будете использовать столько ресурсов сервера, потому что по мере того, как пользователи станут неактивными, их данные сеанса будут удалены.

В качестве примера того, как выполнить скользящее кэширование с истечением срока действия (также ссылается здесь ), вы можете сделать это:

public static void AddToCache(string key, Object value, int slidingMinutesToExpire)
{
        if (slidingMinutesToExpire == 0)
        {
            HttpRuntime.Cache.Insert(key, value, null, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.NotRemovable, null);
        }
        else
        {
            HttpRuntime.Cache.Insert(key, value, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(slidingMinutesToExpire), System.Web.Caching.CacheItemPriority.NotRemovable, null);
        }
    }
...