Вопросы производительности приложений, использующих службы
Обновлен: Ноябрь 2007
В этом разделе обсуждается оптимизация производительности, когда используется членство ASP.NET, роли, свойства профилей, состояние сеанса, персонализация веб-частей и навигация по веб-узлу.
Членство
В этот подраздел включены сведения об эффективном использовании членства ASP.NET.
Эффективный сбор списков членства
При вызове методов класса Membership вызовите перегруженные методы, которые принимают члены PageIndex и PageSize. Эти перегруженные методы выполняются быстрее, так как они приводят к меньшему объему данных, передаваемых с веб-сервера. Примером является метод GetAllUsers класса Membership. Вызов метода GetAllUsers без параметров возвращает всех пользователей членства. И наоборот, вызов перегрузки метода GetAllUsers возвращает только одну страницу пользователей, сокращая объем обрабатываемых страницей данных.
Кэшируйте результаты при возвращении большого числа интерактивных пользователей
Можно вызвать метод GetNumberOfUsersOnline, чтобы отобразить большое число возможных активных пользователей на веб-узле. Этот метод проверяет каждую строку в таблице членства при каждом вызове метода, что может привести к значительному снижению производительности при большом числе пользователей базы данных. Вызывайте этот метод только при необходимости и кэшируйте значение на некоторое время, если нет необходимости в точном подсчете.
Роли
По умолчанию метод GetRolesForUser вызывается при каждой загрузке страницы и возвращает роли, с которыми вошел пользователь. Роли хранятся в словаре в объекте RolePrincipal. С помощью этого словаря выполняется проверка ролей во время запуска веб-страницы. Чтобы запретить обращение к поставщику при каждой загрузке страницы и тем самым сократить время обработки сервером, установите для атрибута CacheRolesInCookie в файле Web.config приложения значение true. В результате, список ролей пользователей будет сохранен в файле «cookie». При следующей загрузке страницы сведения о роли можно считать из файла «cookie» вместо использования вызова поставщика.
Чтобы проверить членство в роли, можно использовать метод GetRolesForUser, свойство IsInRole и метод GetRoles в коде. Если понимать, как взаимодействуют эти методы, можно написать код для приложения, которое будет более эффективно выполнять требуемую задачу.
Метод GetRolesForUser всегда обращается к поставщику. Вызов метода IsInRole всегда приводит к вызову метода GetRolesForUser при первом запросе страницы, если не включено кэширование файла «cookie». Если кэширование файла «cookie» включено, вызовы метода IsInRole вместо этого будут использовать сведения о роли, кэшированные в файле «cookie». Первый вызов метода GetRoles приводит к вызову метода GetRolesForUser независимо от того, включено или выключено кэширование файла «cookie». Хотя последующие вызовы метода GetRoles для страницы используют сведения о роли, кэшированные в объекте RolePrincipal.
Примечание. |
---|
Хранение важных сведений в файле «cookie» может сделать их доступными пользователям. Для максимальной безопасности не включайте кэширование файлов «cookie». |
Свойства профиля
Если код обращается к какому-либо свойству профиля при загрузке страницы, поставщик профиля считывает все свойства профиля для текущего пользователя. (В частности, поставщик считывает все свойства, связанные с данным поставщиком профиля.) Если какие-либо значения свойств изменяются, новые сведения записываются обратно в хранилище данных поставщика при выгрузке страницы. ASP.NET может определить, были ли изменены внутренние типы, такие как целые числа или строки, но не может определить, были ли изменены не внутренние типы.
Алгоритм определения того, были ли свойства профиля сохранены, следующий:
Если типы свойств профиля являются внутренними типами и ни один не был изменен, профиль не записывается в хранилище данных.
Если все типы свойств профиля являются внутренними типами и какой-либо из них был изменен, все значения свойств профиля записываются в хранилище данных.
Если какое-либо свойство не является внутренним типом, ASP.NET не может определить, было ли изменено значение. Если свойство доступно в коде, тогда значение свойства записывается в хранилище данных.
Примечание. Во всех случаях решение применяется ко всем свойствам профиля отдельного поставщика.
Если используются не внутренние типы свойств, запись данных профиля в конце каждого запроса страницы занимает время. Можно снизить эти издержки следующими способами:
Используйте только внутренние типы в профилях.
Установите для атрибута automaticSaveEnabled в элементе конфигурации <profile> значение Off и напишите пользовательский код для определения изменений и сохранения значений свойств при необходимости.
Напишите пользовательский код для обработки события ProfileAutoSaving и в коде события определите, были ли какие-либо изменения в свойствах профилей. Если свойства не были изменены, отмените операцию автоматического сохранения и установите для свойства ContinueWithProfileAutoSave события значение false.
Состояние сеанса
Вопрос производительности рассматривается при использовании режима состояния внешнего сеанса (дополнительные сведения см. в разделе Режимы состояний сеанса). В этом разделе представлены сведения по оптимизации производительности состояния сеанса.
Снижение затрат на считывание и запись состояния сеанса
По умолчанию сведения о состоянии сеанса загружаются при каждой загрузке страницы. Атрибут EnableSessionState в директиве @ Page предоставляет управление загрузкой состояния сеанса с помощью следующих параметров:
True Данные состояния сеанса считываются при каждой загрузке страницы и сохраняются, если были изменены. ASP.NET может определить, были ли изменены внутренние типы, такие как целые числа и строки. Если все значения состояния сеанса являются внутренними типами и не были изменены, сеанс не сохраняется. Если какие-либо значения не являются внутренними типами и имеется доступ к каким-либо не внутренним значениям сеанса, тогда все сведения о состоянии сеанса сохраняются. Это происходит потому, что ASP.NET не отслеживает, были ли изменены не внутренние типы, и выбирает наиболее безопасный способ — сохранение всех данных.
False Данные состояния сеанса не считываются при загрузке страницы.
ReadOnly Данные состояния сеанса считываются при каждой загрузке страницы, но никогда не сохраняются, даже если были изменены значения состояния сеанса в коде.
Исключение блокировок состояния сеанса
Не рекомендуется использовать элементы <IFRAME> на странице, запрашивающей состояние сеанса. Если сделано несколько запросов к ASP.NET с одним и тем же идентификатором состояния сеанса и если все запросы обращаются к страницам, на которых для свойства EnableSessionState задано значение true, тогда будут выполняться параллельные запросы для блокировки, связанной с состоянием внешнего сеанса. В случае если применяются элементы <IFRAME>, это означает, что страницы ASP.NET, отображаемые в нескольких элементах <IFRAME> на странице, могут выполняться для одних и тех же данных сеанса. В результате, каждый отдельный запрос будет сериализоваться на сервере.
Персонализация веб-частей
При запуске страницы загружаются сведения персонализации ASP.NET. Чтобы определить, были ли изменены какие-либо сведения персонализации веб-частей, ASP.NET вызывает метод Equals, чтобы сравнить старые и новые значения свойств, помеченных атрибутом PersonalizableAttribute.
Если какое-либо значение свойства персонализации было изменено, данные персонализации сохраняются. Для внутренних типов, таких как целые числа, метод Equals напрямую сравнивает старые и новые значения свойств. Однако для не внутренних типов ASP.NET сравнивает значение ссылки, но не обязательно данные, обслуживаемые экземпляром типа.
Например, для свойства типа ArrayList метод Equals сравнивает старые и новые значения ссылки ArrayList, но не содержимое объекта ArrayList. Метод Equals вернул бы значение true, если бы ссылка ArrayList не была изменена, даже если был добавлен новый элемент к списку. В этом случае данные ArrayList не были бы сохранены.
Этот алгоритм является эффективным для не внутренних типов, но приводит к ошибке на стороне несохраненных данных. Если требуется сохранить не внутренние типы, такие как объект ArrayList, задайте для свойства IsDirty значение true, если элемент управления происходит от объекта WebPart, или вызовите метод SetPersonalizationDirty, который принимает элемент управления как параметр.
Навигация по веб-узлу
Крупная карта веб-узла приводит к снижению производительности по сравнению с небольшими картами. Например, в тестовом сценарии увеличение числа веб-узлов от 100 до 1000 (десятикратное увеличение) может увеличить время загрузки на треть.
Фильтрация по ролям безопасности, при которой узлы фильтруются на основе ролей, приводит к большему снижению производительности, чем увеличение числа веб-узлов. Например, карта веб-узла с 1000 узлов требует в 10 раз больше ресурсов на обработку, чем карта веб-узла со 100 узлами.
Ниже даны некоторые рекомендации для снижения этого эффекта:
При использовании фильтрации по ролям безопасности рекомендуемое максимальное число узлов — 150.
Установите атрибут Roles в каждом узле карты веб-узла. Если имеется этот атрибут ролей, ASP.NET может обходить URL-адрес и авторизацию файла для URL-адреса, связанного с объектом SiteMapNode, а также авторизацию пользователя, принадлежащего одной из ролей, указанных в атрибуте. Однако обратите внимание, что если пользователь не принадлежит какой-либо из указанных ролей, тогда ASP.NET возвращается к более медленной проверке авторизации файла и URL-адреса.
Создайте класс, который наследует от класса SiteMapProvider и переопределите метод IsAccessibleToUser для проверки только атрибута Roles в каждом узле карты веб-узла. Это ускорит процесс фильтрации, так как выполняется обход авторизации URL-адреса и файла. Однако этот подход требует двух параллельных определений безопасности в веб-приложении. Первое представляет собой сведения авторизации в файле Web.config (и списках контроля доступа для авторизации файла, если включена проверка подлинности Windows). Второе является сведениями о роли в карте веб-узла. Следует взвесить затраты на управление безопасностью, связанные с разделением сведений системы безопасности и повышением производительности обработки карты веб-узла.
Дополнительные сведения см. в разделах Фильтрация карты веб-узла ASP.NET по ролям безопасности и Авторизация в ASP.NET.