Asp избегайте кэшировать медленные компоненты в объектах application или session


Содержание

Является ли кэширование с использованием приложения более медленным или более проблематичным, чем использование статической переменной Global.asax.cs?

У нас есть приложение Webforms, в котором хранится множество настроек и терминологических сопоставлений (несколько сотен), которые используются во всем приложении.

Коллекция Application [] может быть медленнее и сложнее.

объект Application []. неэффективен в ASP.NET.

Это рекомендуется? Да, а не только автором этой статьи. Это отмечено в Professional ASP.NET от Apress и многих сайтах в Интернете. Это работает хорошо

Поэтому мне интересно, верны ли эти утверждения. Может ли кто-нибудь объяснить, почему использование приложения медленнее или какие проблемы могут возникнуть, если вы используете приложение? Я вроде бы предполагаю, что любые проблемы или замедление могут возникать только при производственных нагрузках, поэтому я прошу об опыте реального мира, а не просто тестировании себя.

Я знаю, что существует много альтернатив кешированию (HttpRuntime.Cache, memcached и т.д.), Но я хочу знать, нужно ли мне вернуться и переписать старый код, использующий Application []. В частности, если я каким-либо образом подвергаюсь штрафу за исполнение, я бы хотел избавиться от этого.

Как вы сохраняете эти настройки? Я бы порекомендовал web.config

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

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

Кроме того, переменные в файлах web.config/app.config могут изменяться без изменения кода и/или перекомпиляции вашего проекта.

Класс приложения (глобальные переменные) существует только в ASP.NET, чтобы помочь с обратной совместимостью с классическим ASP, вы можете сказать, что он устарел.

Еще одна вещь, которую вы могли бы изучить, — это кэширование ваших настроек, чтобы вы не всегда читали с диска.

замечания по поводу «25 советов по оптимизации. «

Почитал советы по оптимизации asp-приложений, опубликованные на relib. И по поводу 5го совета (Не кэшируйте соединение БД в объектах Application или Session) возник вопрос.
Создание объекта Connection, несомненно, является очень ресурсоемкой операцией, и было бы здорово оставить его открытым на всю сессию (при необходимости, естественно). Как верно замечено в совете, расширение видимости этого объекта до прикладного уровня (application) создаст узкое место, критичное в плане производительности. Т.к. все юзеры будут вынуждены получать доступ к бд через один объект. В случае создания объекта на уровне сеанса (session), наоборот, у всех юзеров будет собственный объект и ресурсы сервера будут тратиться впустую, т.к. большую часть времени сеанса объект Connection не задействован. Написано все верно, но хотелось бы конкретизировать.
ADO хоть и основана на спецификации OLEDB, но в случае если рбд поддерживает только ODBC, для доступа к рдб используется поставщик данных OLEDB. Интерфейсы которого по сути являются производными от ODBC, и следовательно используют все ее возможности. Про случай использования чистой ODBC я вообще молчу.
Так вот. В состав активного сервера входит ODBC Manager, одним из функций которого является объединение подключений к бд (Connection Pooling). В результате, прежде чем создать новое соединение с бд, ODBC Manager проверяет, нет ли уже созданных, и не используемых какое-то (заданное) время. Если таковые есть, то вместо создания нового объекта, используется существующий. Т.е. висящий Connection передается другому юзеру.
Это имелось в виду, когда говорилось «. IIS автоматически допускает объединение подключений OLEDB и ODBC. »?
И еще один момент… В случае, когда обмен данными между юзером и сервером ведется довольно интенсивно и соединение используется более чем на одной странице (например, различные специализированные интранет проекты). Т.е. Connection необходимо держать открытым во время частого обмена данными, то, для повышения производительности, объект Connection все же следует создавать на уровне сеанса, задействовав при этом connection pooling с не очень большим таймаутом.

Меню пользователя DiP
18.11.2007, 00:13

Как «Истина»/»Ложь» переделать в «True»/»False»?
собснно сабж. есть w2000 server. русский IE. где-то в скрипте на сервере (VB) выдает CStr(True) =.

Ошибка после конвертации метода на С++ к С#: «Неявное преобразование типа «int» в «bool» невозможно»
Ошибка после преобразования метода на С++ к С#: «Неявное преобразование типа «int» в «bool».

Ошибка CS0019: Оператор «*» не может применяться к операндам типа «decimal» и «float»
Здравствуйте! Писал приложение и наткнулся на интересную ошибку (честно говоря, я не совсем понимаю.

Переопределить операции «+» «=» «-» для экземпляров моего класса
Добрый день. Мне нужно переопределить операции «+» «=» «-» для экземпляров моего класса. Я вижу это.

Кэширование данных

Кэширование — это один из способов оптимизации Web приложений. В любом приложении встречаются медленные операции (SQL запросы или запросы к внешним API), результаты которых можно сохранить на некоторое время. Это позволит выполнять меньше таких операций, а большинству пользователей показывать заранее сохраненные данные.

Наиболее популярная технология кеширования для Web приложений — Memcache.

Когда нужно кэшировать

Старайтесь избегать кэширования, пока в этом не будет прямой необходимости. Это простая техника, но это снижает гибкость приложения. Не делайте лишнюю работу заранее, но закладывайте возможность использования кэширования в будущем:

  • Используйте классы или функции, для работы с данными. Не используйте повторяющихся SQL выборок в основном приложении.
  • Используйте обертки для работы с внешними API.

Что кэшировать?

Кэшировать нужно данные, которые медленно генерируются и часто запрашиваются. На практике это обычно:

  • Результаты запросов к внешним сервисам (RSS, SOAP, REST и т.п.).
  • Результаты медленных выборок из базы данных.
  • Сгенерированные html блоки либо целые страницы.

Кэширование выборок из баз данных

Запросы к базе данных — наиболее распространенный пример. На основе Мemcache реализуется очень просто:

# Запрос на получение пользователей кэшируется на 1 час

Обновление данных

Если Вы кэшируете данные, которые могут обновляться, необходимо очищать кэш после каждого обновления:

Кэширование списков

Допустим, Вы кэшируете данные каждого пользователя, как в примере, а также их списки (например, список online пользователей). При обновлении данных пользователя, Вы удаляете данные из кэша только для указанного пользователя. Но его данные могут также присутствовать в списке online пользователей, которые тоже лежат в кэше. Сбрасывать списки при каждом обновлении данных любого пользователя не эффективно. Поэтому обычно используют такой подход:

  1. Кэшируют списки, которые состоят только из ID пользователей.
  2. Для вывода списка отправляют отдельный запрос для получения данных каждого пользователя.

Реализация выглядит так:

# Получим список ID пользователей и для каждого из них получим актуальные данные

Для получения данных сразу нескольких объектов можно использовать Multiget.

Повторные запросы

Некоторые данные могут запрашиваться несколько раз в рамках одной страницы, например:

Каждый вызов get_user() будет получать данные из кэша. Если Memcache стоит на отдельном сервере, это вызовет большой сетевой трафик и задержки.

Чтобы этого избежать, можно использовать дополнительный кэш внутри самого приложения:

В реальных приложениях, имеет смысл иметь обертку для Memcache с дополнительным кэшом:

# $inner_cache хранит дополнительный кэш

Внимание. Использование этого подхода может приводить к утечкам памяти в случаях, когда идет работа с большим количеством данных в кэше. Например, в cron-задачах (допустим, мы перебираем всех пользователей для отправки рассылки). Тогда лучше добавить отключение внутреннего кэша:

# Отключаем внутренний кэш

Подогревание

При обновлении особенно тяжелых данных следует использовать не сброс кэша, а прямое обновление данных в нем:

Это позволит избежать дополнительной нагрузки при выполнении тяжелых выборок, когда ключ удаляется. Такую методику обычно используют в cron задачах, чтобы периодически обновлять результаты очень тяжелых выборок.

Время жизни (ttl)

ttl (время жизни) — это время, после которого, данные будут удалены из кэша. В Memcache устанавливается в секундах:

# Установка ttl на 1 час

Чаще всего ttl ставят от нескольких минут до нескольких дней. Не используйте значение 0 (бесконечное хранение), это может засорить память.

Любой кэш работает по принципу вытеснения если ему не хватает памяти. Т.е. если Memcache может использовать максимум 1G памяти, а Вы пытаетесь сохранить ключей на 2G, то половину из этих данных Memcache удалит. Для определения, какие именно ключи удалять, используется алгоритм LRU (Least Recently Used):

Memcache постарается удалить прежде всего те данные, которые запрашивались очень давно (т.е. менее популярные удалит, а более популярные оставит).

Кэширование очень медленных запросов

Представьте, что у Вас есть запрос, который выполняется 10 секунд. Вы сохраняете его в кэш на 1 час. Когда проходит это время, данные в кэше удаляются. В первые 10 секунд после этого Вы сталкиваетесь с ситуацией, когда несколько пользователей одновременно вызывают этот тяжелейший запрос. Это может привести к катастрофическим последствиям, т.к. в течение 10 секунд может быть несколько сотен или тысяч таких вызовов.

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

Атомарные операции

Иногда в кэше хранятся счетчики (например, количество пользователей). При добавлении новых пользователей, вместо сброса счетчика и повторной выборки, можно просто увеличить значение кэша на единицу. Но сделать это через приложение нельзя, т.к. это приведет к потере данных от двух одновременно выполненных запросов:

Memcache поддерживает две атомарные операции увеличения и уменьшения чисел:

# Увеличит счетчик на 1, функция memcache_decrement() уменьшает счетчик

Самое важное

Кэширование в приложениях на основе Memcache — это очень сильный инструмент. Не забывайте, что Memcache не гарантирует Вам сохранности данных. Это значит, что нельзя рассчитывать на то, что сохраненные на 60 минут данные будут находиться в кэше именно 60 минут.

Оптимизация выборок списков с помощью Multiget

Эффективное использование памяти в Memcache

Простое развертывание приложений и сервисов при помощи Subversion

Развертывание небольших веб-приложений и сервисов с помощью Git

Асинхронные задачи для оптимизации скорости сайта

Как включить хранение PHP сессий в Memcache

Быстрое и простое введение по кэшированию на PHP и Memcache

Кэширование динамических страниц с помощью SSI

5 методик использования lazy loading для оптимизации

Улучшение производительности PHP приложений

Правильный подход для кэширования тяжелых запросов

Как настроить веб-сервер Nginx для работы с Magento

Небанальные советы, способные упростить работу с Git

Что делать, если часть логики написана на PHP, а часть на NodeJS

Анализ медленных PHP скриптов с помощью XHprof

Включение и использование логов ошибок, запросов и медленных запросов, бинарного лога для проверки работы MySQL

Методы улучшения производительности веб-приложения для высоконагруженных проектов на Django

Выбор серверов под базы данных, бекенды и фронтенды

Настройки для улучшения производительности Postgres

Основная информация о Amazon S3


Небольшие советы для упрощения работы с Subversion

Check-unused-keys для определения неиспользуемых индексов в базе данных

Как мне улучшить ASP.NET производительность приложения MVC?

Как вы улучшаете свой ASP.NET производительность приложения MVC?

16 ответов

ниже приведен список возможных источников улучшения:

общие

  • используйте профилировщик для обнаружения утечек памяти и проблем с производительностью в приложении. лично я предлагаю dotTrace
  • запуск сайта в режиме выпуска, а не отладки, Когда в производстве, а также во время профилирования производительности. Режим выпуска намного быстрее. Режим отладки может скрыть проблемы производительности в вашем собственном код.

кэширование

  • использовать CompiledQuery.Compile() рекурсивно избегая перекомпиляция запроса выражения
  • кэш не подвержен изменениям содержание с помощью OutputCacheAttribute чтобы сохранить ненужное и действие казни
  • используйте cookies для часто доступной не конфиденциальной информации
  • использовать теги ETag и срок действия-напишите свой заказ ActionResult методы при необходимости
  • рассмотреть с помощью RouteName для организации маршрутов, а затем использовать его для создания ваши ссылки и старайтесь не использовать метод ActionLink на основе дерева выражений.
  • рассмотрите возможность реализации стратегии кэширования разрешения маршрута
  • поставить повторяющийся код внутри PartialViews , не сделать его xxxx раз: если вы в конечном итоге вызов одного и того же частичного 300 раз в том же представлении, вероятно, есть что-то это неправильно. Объяснение И Контрольные показатели

маршрут

разрешение маршрута кэша с помощью этого помощника UrlHelperCached ASP.NET выступление MVC Руди Бенковича

безопасность

  • используйте проверку подлинности форм, держите часто доступ конфиденциальные данные в билет аутентификации

даль

  • при доступе к данным через LINQ положитесь на IQueryable
  • использовать шаблон репозитория
  • профилируйте свои запросы, т. е. Uber Profiler
  • рассмотрим кэш второго уровня для ваших запросов и добавьте им область и тайм-аут, т. е. NHibernate Второй Кэш

балансировки нагрузки

используйте обратные прокси, чтобы распределить нагрузку клиента по вашему экземпляру приложения. (Stack Overflow использует HAProxy (в MSDN).

использовать Асинхронные Контроллеры для реализации действий, зависящих от обработки внешних ресурсов.

клиент сторона

  • оптимизируйте свою клиентскую сторону, используйте такой инструмент, как YSlow для предложения по повышению производительности
  • используйте AJAX для обновления компонентов вашего пользовательского интерфейса, избегайте обновления всей страницы, когда это возможно.
  • рассмотрите возможность реализации архитектуры pub-sub-т. е. Comet-для доставки контента против Перезагрузка на основе таймаутов.
  • по возможности переместите логику построения графиков и графиков на сторону клиента. Генерация графов это дорогостоящая деятельность. Перенос на клиентскую сторону вашего сервера ненужная нагрузка, и позволяет работать с графиками локально без создания нового запрос (т. е. гибкий график, jqbargraph, MoreJqueryCharts).
  • используйте CDN для скриптов и медиаконтента для улучшения загрузки на стороне клиента (т. е. Google CDN)
  • Minify -Compile- ваш JavaScript для того, чтобы улучшить свой скрипт размер
  • держите размер куки небольшим, так как куки отправляются на сервер по каждому запросу.
  • рассмотрите возможность использования DNS и предварительная выборка ссылок когда это возможно.

глобальная конфигурация

если вы используете Razor, добавьте следующий код в свой глобальный.асакс.cs, по умолчанию, Asp.Net MVC визуализирует с движком aspx и движком razor. Это использует только RazorViewEngine.

ViewEngines.Engines.Clear(); ViewEngines.Engines.Add(new RazorViewEngine());

добавить gzip (сжатие HTTP) и статический кэш (изображения, css, . ) в интернете.конфиг

  • удалить неиспользуемые модули HTTP
  • очистите HTML, как только он будет сгенерирован (в вашем интернете.config) и отключить viewstate, если вы его не используете

    Альпинист Код и запись в блоге предоставьте подробные способы повышения производительности приложения.

    скомпилированный запрос повысит производительность вашего приложения, но не имеет ничего общего с ASP.NET MVC. Это ускорит каждое приложение db, поэтому на самом деле речь идет не о MVC.

    основное предложение следовать принципы отдыха и следующие моменты связывают некоторые из этих принципов с ASP.NET MVC framework:

    1. сделать ваши контроллеры — это больше ‘Web предложение производительности / масштабируемости (в отличие от производительности микро / машинного уровня) и важное дизайнерское решение, которое повлияет на ваше будущее приложений — особенно в случае, если оно станет популярным или если вам нужна ошибка например, терпимость.
      • не использовать сессии
      • не используйте tempdata-который использует сеансы
      • Не пытайтесь «кэшировать» все «преждевременно».
    2. использовать Проверка Подлинности С Помощью Форм
      • храните ваши часто доступные конфиденциальные данные в билете аутентификации
    3. используйте cookies для часто доступной не конфиденциальной информации
    4. сделать ваши cachable ресурсов в интернете
      • Использовать ETags
      • использовать срок годности
      • при необходимости напишите свои пользовательские классы ActionResult
      • использовать обратный прокси
    5. скомпилируйте свой JavaScript. существует библиотека компилятора закрытия чтобы сделать это (конечно есть и другие, просто найдите «JavaScript compiler» тоже)
    6. Использовать CDNs (Сеть доставки контента) — особенно для больших медиа-файлов и так далее.
    7. рассмотрите различные типы хранения ваших данных,например, файлы, хранилища ключей / значений и т. д. — не только SQL Server
    8. и последнее, но не менее важное: проверьте свой веб-сайт на производительность

    Это может показаться очевидным, но Запустите свой сайт в режиме выпуска, а не в режиме отладки, Когда в производстве, а также во время профилирования производительности. Режим выпуска —много быстрее. Режим отладки может скрыть проблемы производительности в вашем собственном коде.

    при доступе к данным через LINQ полагайтесь на IQueryable .

    . и leverge хороший шаблон репозитория:

    это оптимизирует доступ к данным, чтобы обеспечить загрузку только необходимых данных и только тогда, когда это необходимо.

    не потрясающая оптимизация, но я думал, что выброшу это там -используйте CDN для jQuery и т. д..

    цитата из самого Скоттгу: Microsoft Ajax CDN позволяет значительно улучшить производительность ASP.NET веб-формы и ASP.NET приложения MVC, которые используют ASP.NET AJAX или jQuery. Услуга предоставляется бесплатно, не требует регистрации и может быть использован как для коммерческого, так и некоммерческого цели.

    мы даже используем CDN для наших веб-частей в Moss, которые используют jQuery.

    также, если вы используете NHibernate вы можете включить и настроить кэш второго уровня для запросов и добавить в область запросов и тайм-аут. И есть kick ass profiler для EF, L2S и NHibernate -http://hibernatingrhinos.com/products/UberProf. Это поможет настроить ваши запросы.

    Использовать Спрайты: спрайты-отличная вещь, чтобы уменьшить запрос. Вы объединяете все свои изображения в один и используете CSS, чтобы получить хорошее часть спрайта. Microsoft предоставляет хорошую библиотеку для этого: Спрайт и оптимизация изображений предварительный просмотр 4.

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

    использовать ADO.NET вместо Entity Framework: EF4 or EF5 отлично подходят для сокращения времени разработки, но будет больно оптимизировать. Проще оптимизировать a хранимая процедура чем сущность Рамки. Поэтому вы должны использовать процедуры магазина как можно больше. Dapper предоставляет простой способ запроса и сопоставления SQL с очень хорошим спектакль.

    страница кэша или частичная страница: MVC предоставляет простой фильтр для кэширования страницы в соответствии с некоторыми параметрами, поэтому используйте его.

    уменьшить вызовы базы данных: можно создать уникальный запрос базы данных, возвращающий несколько объектов. Проверьте на веб-сайте Dapper.

    всегда иметь чистую архитектуры: имейте чистую архитектуру n-ярусов, даже на небольшом проекте. Это поможет вам сохранить ваш код чистым и будет легче оптимизировать если понадобится.

    вы можете взглянуть на этот шаблон «шаблон MVC Neos-SDI» который создаст чистую архитектуру для вас с большим количеством повышение производительности по умолчанию (check MvcTemplate вебсайт.)

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

    Илон Маск рекомендует:  Использование checked

    Это относится ко всем сайтам, а не только ASP.NET MVC.

    одна очень простая вещь — думать асинхронно при доступе к данным, которые вы хотите для страницы. Независимо от того, чтение из веб-службы, файла, базы данных или чего-то еще, используйте асинхронную модель как можно больше. Хотя это не обязательно поможет любой одной странице быть быстрее, это поможет вашему серверу работать лучше в целом.

    1: Получить Тайминги. Пока вы не знаете, где замедление, вопрос слишком широк, чтобы ответить. Проект, над которым я работаю, имеет эту точную проблему; нет регистрации, чтобы даже знать, сколько времени занимают определенные вещи; мы можем только догадываться о медленных частях приложения, пока мы не добавим тайминги в проект.

    2: Если у вас есть последовательные операции, не бойтесь слегка многопоточной. Особенно если задействованы блокирующие операции. PLINQ является вашим другом здесь.

    3: Предварительно создайте представления MVC при публикации. Это поможет с некоторыми из «первой страницы хит»

    4: Некоторые утверждают, что хранимая процедура/ADO преимущества скорости. Другие выступают за скорость развития эф и более четкое разделение ярусов и их назначение. Я видел очень медленные проекты, когда SQL и обходные пути для использования Sprocs/Views для извлечения и хранения данных. Кроме того, ваша трудность для тестирования повышается. Наша текущая кодовая база, которую мы преобразуем из ADO в EF, не выполнение любого хуже (и в некоторых случаях лучше), чем старая ручная модель.

    5: что сказал, Подумайте о применении разминки. Частью того, что мы делаем, чтобы помочь устранить большинство наших проблем с производительностью EF, было добавление специального метода разминки. Он не предварительно компилирует какие-либо запросы или что-то еще, но он помогает с большей частью загрузки/генерации метаданных. Это может быть еще более важно при работе с первыми моделями кода.

    6: Как говорили другие, не используйте состояние сеанса или ViewState, если это возможно. Это не обязательно оптимизация производительности, о которой думают разработчики, но как только вы начинаете писать более сложные веб-приложения, вам нужна отзывчивость. Состояние сеанса исключает это. Представьте себе длительный запрос. Вы решаете открыть новое окно и попробовать менее сложное. Ну, вы также можете подождать с состоянием сеанса, потому что сервер будет ждать, пока первый запрос не будет выполнен, прежде чем перейти к следующему для этого сеанса.

    7: Минимизировать обращения к базе данных. Сохраните материал, который вы часто используете, но не будете реально меняться в кэш .Net. Попробуйте пакетной вставки/обновления, где это возможно.

    7.1: избегайте кода доступа к данным в ваших представлениях Razor без чертовски веской причины. Я бы не говорил этого, если бы не видел. Они уже получали доступ к своим данным, когда собирали модель, почему, черт возьми, они не включали ее в модель?

    просто хотел добавить мои 2 цента. Наиболее эффективным способом оптимизации генерации URL-маршрута в приложении MVC является. не создавать их вообще.

    большинство из нас более или менее знают, как URL-адреса генерируются в наших приложениях в любом случае, так что просто используя static Url.Content(«

    /Blahblah») вместо Url.Action() или Url.RouteUrl() где это возможно, бьет все другие методы почти в 20 раз и даже больше.

    PS. Я провел тест из нескольких тысяч итераций и опубликовал результаты на мой блог если интересно.

    в вашем шуме, чтобы оптимизировать клиентскую сторону, не забывайте о слое базы данных. У нас было приложение, которое шло от 5 секунд, чтобы загрузить до 50 секунд за ночь.

    при проверке мы сделали целую кучу изменений схемы. Как только мы обновили статистику, она внезапно стала такой же отзывчивой, как и раньше.

    1. Реализовать Gzip.
    2. используйте асинхронную отрисовку для частичных представлений.
    3. минимизировать попадания в базы данных.
    4. используйте скомпилированный запрос.
    5. запустите профилировщик и найдите ненужные хиты. Оптимизируйте все хранимые процедуры, которые занимают более 1 секунды для возврата ответа.
    6. использовать кэширование.
    7. использовать комплектация minification оптимизация.
    8. используйте утилиты HTML 5, такие как кэш сеанса и локальный хранение только для чтения содержимого.

    такие вещи делать

    1. кэш режима ядра
    2. режим трубопровода
    3. удалить неиспользуемые модули
    4. runAllManagedModulesForAllRequests
    5. не пишите в wwwroot
    6. удалить неиспользуемые двигатели просмотра и язык

    используя связывать и Minification также помогает вам улучшить представление. Это в основном сокращает время загрузки страницы.

    Состояние сеанса и приложения в ASP.NET Core Session and app state in ASP.NET Core

    HTTP — это протокол без отслеживания состояния. HTTP is a stateless protocol. Без дополнительных действий HTTP-запросы являются независимыми сообщениями, которые не сохраняют значения пользователя или состояние приложения. Without taking additional steps, HTTP requests are independent messages that don’t retain user values or app state. В этой статье описывается несколько подходов для сохранения данных пользователя и состояния приложения между запросами. This article describes several approaches to preserve user data and app state between requests.

    Управление состоянием State management


    Состояние можно сохранить несколькими способами. State can be stored using several approaches. Эти способы обсуждается ниже в данном разделе. Each approach is described later in this topic.

    Способ хранения данных Storage approach Механизм хранения Storage mechanism
    Файлы «cookie» Cookies Файлы cookie HTTP (могут содержать данные, сохраненные с помощью кода приложения на стороне сервера) HTTP cookies (may include data stored using server-side app code)
    Состояние сеанса Session state Файлы cookie HTTP и код приложения на стороне сервера HTTP cookies and server-side app code
    TempData TempData Файлы cookie HTTP или состояние сеанса HTTP cookies or session state
    Строки запросов Query strings Строки запросов HTTP HTTP query strings
    Скрытые поля Hidden fields Поля формы HTTP HTTP form fields
    HttpContext.Items HttpContext.Items Код приложения на стороне сервера Server-side app code
    Кэш Cache Код приложения на стороне сервера Server-side app code
    Введение зависимостей Dependency Injection Код приложения на стороне сервера Server-side app code

    Файлы cookie хранят данные между запросами. Cookies store data across requests. Так как файлы cookie отправляются с каждым запросом, их размер нужно свести к минимуму. Because cookies are sent with every request, their size should be kept to a minimum. В идеальном случае файл cookie должен содержать лишь идентификатор, а сами данные хранятся в приложении. Ideally, only an identifier should be stored in a cookie with the data stored by the app. Большинство браузеров позволяют использовать файлы cookie размером до 4096 байт. Most browsers restrict cookie size to 4096 bytes. Для каждого домена доступно лишь ограниченное число файлов cookie. Only a limited number of cookies are available for each domain.

    Так как файлы cookie могут быть незаконно изменены, их нужно проверять в приложении. Because cookies are subject to tampering, they must be validated by the app. Файлы cookie могут удаляться пользователем и имеют ограниченный срок хранения на клиентах. Cookies can be deleted by users and expire on clients. Тем не менее файлы cookie обычно являются самым надежным способом хранения данных на стороне клиента. However, cookies are generally the most durable form of data persistence on the client.

    Файлы cookie часто используются для персонализации, когда содержимое настраивается под известного пользователя. Cookies are often used for personalization, where content is customized for a known user. В большинстве случаев пользователь проходит только идентификацию, а не проверку подлинности. The user is only identified and not authenticated in most cases. Файл cookie может хранить имя пользователя, имя учетной записи или уникальный идентификатор пользователя (например, GUID). The cookie can store the user’s name, account name, or unique user ID (such as a GUID). Затем можно использовать файл cookie для доступа к личным настройкам пользователя, таким как цвет фона на веб-сайте. You can then use the cookie to access the user’s personalized settings, such as their preferred website background color.

    Помните об Общем регламенте по защите данных в ЕС (GDPR) при создании файлов cookie и решении вопросов с конфиденциальностью. Be mindful of the European Union General Data Protection Regulations (GDPR) when issuing cookies and dealing with privacy concerns. Дополнительные сведения см. в разделе Общий регламент по защите данных (GDPR), принятый в ЕС, в ASP.NET Core. For more information, see General Data Protection Regulation (GDPR) support in ASP.NET Core.

    Состояние сеанса Session state

    Состояние сеанса — это сценарий ASP.NET Core для хранения пользовательских данных, когда пользователь находится в веб-приложении. Session state is an ASP.NET Core scenario for storage of user data while the user browses a web app. Состояние сеанса использует хранилище, обслуживаемое приложением, для сохранения данных между запросами от клиента. Session state uses a store maintained by the app to persist data across requests from a client. Данные сеанса поддерживаются кэшем и считаются временными, — сайт должен работать и без данных сеанса. The session data is backed by a cache and considered ephemeral data—the site should continue to function without the session data. Критически важные данные приложения должны храниться в пользовательской базе данных и кэшироваться в сеансе только в качестве оптимизации производительности. Critical application data should be stored in the user database and cached in session only as a performance optimization.

    Сеанс не поддерживается в приложениях SignalR, так как хаб SignalR может выполняться независимо от контекста HTTP. Session isn’t supported in SignalR apps because a SignalR Hub may execute independent of an HTTP context. Например, это может произойти, если хаб поддерживает длительный запрос на опрос открытым, когда время существования контекста HTTP для запроса уже истекло. For example, this can occur when a long polling request is held open by a hub beyond the lifetime of the request’s HTTP context.

    ASP.NET Core сохраняет состояние сеанса, предоставляя клиенту файл cookie, содержащий идентификатор сеанса, который отправляется в приложение вместе с каждым запросом. ASP.NET Core maintains session state by providing a cookie to the client that contains a session ID, which is sent to the app with each request. Приложение использует этот идентификатор для получения данных сеанса. The app uses the session ID to fetch the session data.

    Состояние сеанса реагирует на события следующим образом: Session state exhibits the following behaviors:

    • Так как файл cookie сеанса относится к конкретному браузеру, обеспечить общий доступ к сеансам из разных браузеров невозможно. Because the session cookie is specific to the browser, sessions aren’t shared across browsers.
    • Файлы cookie сеанса удаляются при завершении сеанса браузера. Session cookies are deleted when the browser session ends.
    • Если получен файл cookie для просроченного сеанса, создается сеанс, использующий этот же файл. If a cookie is received for an expired session, a new session is created that uses the same session cookie.
    • Пустые сеансы не сохраняются — в сеансе должно быть хотя бы одно значение, чтобы его можно быть сохранить между запросами. Empty sessions aren’t retained—the session must have at least one value set into it to persist the session across requests. Если сеанс не сохраняется, для каждого нового запроса создается новый идентификатор сеанса. When a session isn’t retained, a new session ID is generated for each new request.
    • Приложение хранит сеанс некоторое время после последнего запроса. The app retains a session for a limited time after the last request. Приложение устанавливает время ожидания сеанса или использует значение по умолчанию, равное 20 минутам. The app either sets the session timeout or uses the default value of 20 minutes. Состояние сеанса оптимально подходит для сохранения пользовательских данных, относящихся к определенному сеансу, которые не требуется хранить бессрочно для нескольких сеансов. Session state is ideal for storing user data that’s specific to a particular session but where the data doesn’t require permanent storage across sessions.
    • Данные сеанса удаляются при вызове реализации ISession.Clear или когда истекает срок действия сеанса. Session data is deleted either when the ISession.Clear implementation is called or when the session expires.
    • Не существует механизма по умолчанию, который бы информировал код приложения о том, что браузер клиента закрыт или файл cookie сеанса удален или просрочен на клиенте. There’s no default mechanism to inform app code that a client browser has been closed or when the session cookie is deleted or expired on the client.
    • Шаблоны ASP.NET Core MVC и Razor Pages поддерживают общий регламент по защите данных (GDPR). The ASP.NET Core MVC and Razor pages templates include support for General Data Protection Regulation (GDPR). Файлы cookie для состояния сеанса не помечаются как основные по умолчанию, поэтому состояние сеанса недоступно, если отслеживание разрешено посетителем сайта. Session state cookies aren’t marked essential by default, so session state isn’t functional unless tracking is permitted by the site visitor. Дополнительные сведения можно найти по адресу: Поддержка Общий регламент по защите данных (GDPR) в ASP.NET Core. For more information, see Поддержка Общий регламент по защите данных (GDPR) в ASP.NET Core.

    Не храните конфиденциальные данные в состоянии сеанса. Don’t store sensitive data in session state. Пользователь может не закрывать браузер и очистить файл cookie сеанса. The user might not close the browser and clear the session cookie. Некоторые браузеры сохраняют файлы cookie сеанса в нескольких окнах браузера. Some browsers maintain valid session cookies across browser windows. Сеанс может быть не ограничен одним пользователем — следующий пользователь продолжит использовать приложение с тем же файлом cookie сеанса. A session might not be restricted to a single user—the next user might continue to browse the app with the same session cookie.

    Поставщик кэша в памяти хранит данные сеанса в памяти сервера, содержащего приложение. The in-memory cache provider stores session data in the memory of the server where the app resides. В сценарии с фермой серверов: In a server farm scenario:

    • Используйте прикрепленные сеансы для привязки сеанса к конкретному экземпляру приложения на отдельном сервере. Use sticky sessions to tie each session to a specific app instance on an individual server. Служба приложений Azure использует маршрутизацию запросов приложений (ARR), чтобы прикрепленные сеансы создавались по умолчанию. Azure App Service uses Application Request Routing (ARR) to enforce sticky sessions by default. Однако прикрепленные сеансы могут негативно повлиять на масштабируемость и усложнить обновление веб-приложений. However, sticky sessions can affect scalability and complicate web app updates. Лучше использовать распределенные кэши SQL Server или Redis, для которых прикрепленные сеансы не требуются. A better approach is to use a Redis or SQL Server distributed cache, which doesn’t require sticky sessions. Дополнительные сведения можно найти по адресу: Распределенное кэширование в ASP.NET Core. For more information, see Распределенное кэширование в ASP.NET Core.
    • Файл cookie сеанса шифруется через IDataProtector. The session cookie is encrypted via IDataProtector. Необходимо правильно настроить защиту данных, чтобы читать файлы cookie сеанса на каждом компьютере. Data Protection must be properly configured to read session cookies on each machine. Дополнительные сведения см. статьях Защита данных в ASP.NET Core и Key storage providers in ASP.NET Core (Поставщики хранилища ключей в ASP.NET Core). For more information, see Защита данных в ASP.NET Core and Key storage providers.

    Настройка состояния сеанса Configure session state

    Пакет Microsoft.AspNetCore.Session, который входит в метапакет Microsoft.AspNetCore.App, предоставляет ПО промежуточного слоя для управления состоянием сеанса. The Microsoft.AspNetCore.Session package, which is included in the Microsoft.AspNetCore.App metapackage, provides middleware for managing session state. Чтобы включить сеанс ПО промежуточного слоя для сеансов, Startup должен содержать: To enable the session middleware, Startup must contain:

    • Любой из кэшей памяти IDistributedCache, Any of the IDistributedCache memory caches. при этом реализация IDistributedCache используется в качестве резервного хранилища для сеанса. The IDistributedCache implementation is used as a backing store for session. Дополнительные сведения можно найти по адресу: Распределенное кэширование в ASP.NET Core. For more information, see Распределенное кэширование в ASP.NET Core.
    • Вызов AddSession в ConfigureServices . A call to AddSession in ConfigureServices .
    • Вызов UseSession в Configure . A call to UseSession in Configure .

    Следующий код показывает, как настроить поставщик сеансов в памяти с реализацией в памяти IDistributedCache по умолчанию: The following code shows how to set up the in-memory session provider with a default in-memory implementation of IDistributedCache :

    Порядок ПО промежуточного слоя важен. The order of middleware is important. В предыдущем примере исключение InvalidOperationException возникает при вызове UseSession после UseMvc . In the preceding example, an InvalidOperationException exception occurs when UseSession is invoked after UseMvc . Дополнительные сведения см. в разделе Порядок расположения ПО промежуточного слоя. For more information, see Middleware Ordering.

    После настройки состояния сеанса доступно свойство HttpContext.Session. HttpContext.Session is available after session state is configured.

    Невозможно получить доступ к HttpContext.Session до вызова UseSession . HttpContext.Session can’t be accessed before UseSession has been called.

    Невозможно создать новый сеанс с новым файлом cookie сеанса после того, как приложение начинает запись в поток ответа. A new session with a new session cookie can’t be created after the app has begun writing to the response stream. Исключение записывается в журнал веб-сервера и не отображается в браузере. The exception is recorded in the web server log and not displayed in the browser.

    Асинхронная загрузка состояния сеанса Load session state asynchronously

    Поставщик сеансов по умолчанию в ASP.NET Core загружает запись сеанса из резервного хранилища IDistributedCache в асинхронном режиме только при явном вызове метода ISession.LoadAsync перед методами TryGetValue, Set или Remove. The default session provider in ASP.NET Core loads session records from the underlying IDistributedCache backing store asynchronously only if the ISession.LoadAsync method is explicitly called before the TryGetValue, Set, or Remove methods. Если LoadAsync не вызывается первым, базовая запись сеанса загружается синхронно, что может негативно повлиять на производительность. If LoadAsync isn’t called first, the underlying session record is loaded synchronously, which can incur a performance penalty at scale.

    Чтобы принудительно использовать этот режим в приложениях, используйте для реализаций DistributedSessionStore и DistributedSession оболочку из версий, которые выдают исключение, когда метод LoadAsync не вызывается перед TryGetValue , Set или Remove . To have apps enforce this pattern, wrap the DistributedSessionStore and DistributedSession implementations with versions that throw an exception if the LoadAsync method isn’t called before TryGetValue , Set , or Remove . Зарегистрируйте версии оболочки в контейнере служб. Register the wrapped versions in the services container.

    Параметры сеанса Session options

    Чтобы переопределить значения по умолчанию для сеанса, используйте SessionOptions. To override session defaults, use SessionOptions.

    Параметр Option ОПИСАНИЕ Description
    Файл cookie Cookie Определяет параметры, используемые для создания файлов cookie. Determines the settings used to create the cookie. Параметр Name по умолчанию имеет значение SessionDefaults.CookieName ( .AspNetCore.Session ). Name defaults to SessionDefaults.CookieName ( .AspNetCore.Session ). Параметр Path по умолчанию имеет значение SessionDefaults.CookiePath ( / ). Path defaults to SessionDefaults.CookiePath ( / ). Параметр SameSite по умолчанию имеет значение SameSiteMode.Lax ( 1 ). SameSite defaults to SameSiteMode.Lax ( 1 ). Параметр HttpOnly по умолчанию имеет значение true . HttpOnly defaults to true . Параметр IsEssential по умолчанию имеет значение false . IsEssential defaults to false .
    IdleTimeout IdleTimeout IdleTimeout указывает, как долго сеанс может быть неактивным, прежде чем его содержимое отбрасывается. The IdleTimeout indicates how long the session can be idle before its contents are abandoned. Каждый доступ к сеансу сбрасывает время ожидания. Each session access resets the timeout. Этот параметр применяется только к содержимому сеанса, а не к файлу cookie. This setting only applies to the content of the session, not the cookie. Значение по умолчанию — 20 минут. The default is 20 minutes.
    IOTimeout IOTimeout Максимальный период загрузки сеанса из хранилища или его сохранения обратно в хранилище. The maximum amount of time allowed to load a session from the store or to commit it back to the store. Этот параметр может применяться только к асинхронным операциям. This setting may only apply to asynchronous operations. Время ожидания можно отключить с помощью InfiniteTimeSpan. This timeout can be disabled using InfiniteTimeSpan. Значение по умолчанию — 1 минута. The default is 1 minute.

    Сеанс использует файл cookie для отслеживания и идентификации запросов в одном браузере. Session uses a cookie to track and identify requests from a single browser. По умолчанию этот файл cookie называется .AspNetCore.Session и использует путь / . By default, this cookie is named .AspNetCore.Session , and it uses a path of / . Так как по умолчанию файл cookie не указывает домен, он остается недоступным для клиентского сценария на странице (так как HttpOnly по умолчанию имеет значение true ). Because the cookie default doesn’t specify a domain, it isn’t made available to the client-side script on the page (because HttpOnly defaults to true ).

    Чтобы переопределить файл cookie по умолчанию для сеанса, используйте SessionOptions : To override cookie session defaults, use SessionOptions :

    Приложение использует свойство IdleTimeout, чтобы определить, как долго сеанс может оставаться неактивным до сброса его содержимого в кэше сервера. The app uses the IdleTimeout property to determine how long a session can be idle before its contents in the server’s cache are abandoned. Это свойство не зависит от срока действия файла cookie. This property is independent of the cookie expiration. Каждый запрос, проходящий через ПО промежуточного слоя сеанса, сбрасывает это время ожидания. Each request that passes through the Session Middleware resets the timeout.

    Состояние сеанса является неблокирующим. Session state is non-locking. Когда два запроса пытаются изменить содержимое сеанса, последний из них переопределяет первый. If two requests simultaneously attempt to modify the contents of a session, the last request overrides the first. Session реализован в виде согласованного сеанса, что означает, что все содержимое хранится вместе. Session is implemented as a coherent session, which means that all the contents are stored together. Когда два запроса пытаются изменить разные значения сеанса, последний запрос может переопределить изменения, внесенные первым. When two requests seek to modify different session values, the last request may override session changes made by the first.

    Установка и получение значений сеанса Set and get Session values

    Получить доступ к состоянию сеанса можно через класс Razor Pages PageModel или класс MVC Controller со свойством HttpContext.Session. Session state is accessed from a Razor Pages PageModel class or MVC Controller class with HttpContext.Session. Оно является реализацией ISession. This property is an ISession implementation.

    Реализация ISession предоставляет несколько методов расширения для задания и извлечения значений типа integer и string. The ISession implementation provides several extension methods to set and retrieve integer and string values. Методы расширения находятся в пространстве имен Microsoft.AspNetCore.Http (добавьте оператор using Microsoft.AspNetCore.Http; , чтобы получить доступ к методам расширения), когда проект ссылается на пакет Microsoft.AspNetCore.Http.Extensions. The extension methods are in the Microsoft.AspNetCore.Http namespace (add a using Microsoft.AspNetCore.Http; statement to gain access to the extension methods) when the Microsoft.AspNetCore.Http.Extensions package is referenced by the project. Оба пакета входят в метапакет Microsoft.AspNetCore.App. Both packages are included in the Microsoft.AspNetCore.App metapackage.

    Методы расширения ISession : ISession extension methods:

    В следующем примере извлекается значение сеанса для ключа IndexModel.SessionKeyName ( _Name в примере приложения) на странице Razor Pages: The following example retrieves the session value for the IndexModel.SessionKeyName key ( _Name in the sample app) in a Razor Pages page:

    В следующем примере показано, как задать, а затем получить значения integer и string: The following example shows how to set and get an integer and a string:

    Все данные сеанса должны быть сериализованы, чтобы использовать сценарий-распределенного кэша даже при использовании кэша в памяти. All session data must be serialized to enable a distributed cache scenario, even when using the in-memory cache. Предоставляются минимальные сериализаторы строки и числа (см. методы и методы расширения ISession). Minimal string and number serializers are provided (see the methods and extension methods of ISession). Сложные типы должны быть сериализованы пользователем с помощью другого механизма, например JSON. Complex types must be serialized by the user using another mechanism, such as JSON.

    Добавьте приведенные ниже методы расширения, чтобы задавать и получать сериализуемые объекты: Add the following extension methods to set and get serializable objects:

    Следующий пример показывает, как задать и получить сериализуемый объект с помощью методов расширения: The following example shows how to set and get a serializable object with the extension methods:

    TempData TempData

    ASP.NET Core предоставляет TempData Razor Pages или TempData контроллера. ASP.NET Core exposes the Razor Pages TempData or Controller TempData. Это свойство хранит данные до тех пор, пока они не будут прочитаны в другом запросе. This property stores data until it’s read in another request. Для проверки данных без удаления можно использовать методы Keep(String) и Peek(String) в конце запроса. Keep(String) and Peek(string) methods can be used to examine the data without deletion at the end of the request. Keep() помечает все элементы в словаре для хранения. Keep() marks all items in the dictionary for retention. TempData особенно удобно использовать для перенаправления, когда данные требуются для нескольких запросов. TempData is particularly useful for redirection when data is required for more than a single request. TempData реализуется поставщиками TempData , например, с помощью файлов cookie или состояния сеанса. TempData is implemented by TempData providers using either cookies or session state.

    Примеры TempData TempData samples

    Рассмотрим следующую страницу, которая создает клиент: Consider the following page that creates a customer:

    На следующей странице отображается TempData[«Message»] : The following page displays TempData[«Message»] :

    В предыдущей разметке в конце запроса TempData[«Message»] не удаляется, так как используется Peek . In the preceding markup, at the end of the request, TempData[«Message»] is not deleted because Peek is used. На обновляемой странице отображается TempData[«Message»] . Refreshing the page displays TempData[«Message»] .

    Следующая разметка похожа на приведенный выше код, но в ней используется Keep для сохранения данных в конце запроса: The following markup is similar to the preceding code, but uses Keep to preserve the data at the end of the request:

    При переходе между страницами IndexPeek и IndexKeep TempData[«Message»] не удаляется. Navigating between the IndexPeek and IndexKeep pages won’t delete TempData[«Message»] .

    Следующий код отображает TempData[«Message»] , но в конце запроса TempData[«Message»] удаляется: The following code displays TempData[«Message»] , but at the end of the request, TempData[«Message»] is deleted:

    Поставщики TempData TempData providers

    Поставщик TempData, основанный на файлах cookie, используется по умолчанию для хранения TempData в файлах cookie. The cookie-based TempData provider is used by default to store TempData in cookies.

    Данные в файле cookie шифруются с помощью IDataProtector, кодируются с помощью Base64UrlTextEncoder, а затем фрагментируются. The cookie data is encrypted using IDataProtector, encoded with Base64UrlTextEncoder, then chunked. Так как файл cookie фрагментируется, ограничение на размер одного такого файла, заданное в ASP.NET Core 1.x, не применяется. Because the cookie is chunked, the single cookie size limit found in ASP.NET Core 1.x doesn’t apply. Данные файла cookie не сжимаются, так как сжатие зашифрованных данных может привести к проблемам с безопасностью, например атакам CRIME и BREACH. The cookie data isn’t compressed because compressing encrypted data can lead to security problems such as the CRIME and BREACH attacks. Дополнительные сведения на поставщике TempData, основанном на файлах cookie, см. в разделе CookieTempDataProvider. For more information on the cookie-based TempData provider, see CookieTempDataProvider.

    Выбор поставщика TempData Choose a TempData provider

    Выбор поставщика TempData включает в себя несколько аспектов: Choosing a TempData provider involves several considerations, such as:

    1. Приложение уже использует состояние сеанса? Does the app already use session state? Если это так, использование поставщика TempData для состояния сеанса не требует от приложения никаких дополнительных издержек (кроме объема данных). If so, using the session state TempData provider has no additional cost to the app (aside from the size of the data).
    2. Приложение использует TempData лишь ограниченно, для сравнительно небольших объемов данных (до 500 байт)? Does the app use TempData only sparingly for relatively small amounts of data (up to 500 bytes)? Если это так, поставщик TempData на основе файлов cookie незначительно увеличивает издержки для каждого запроса, переносящего TempData. If so, the cookie TempData provider adds a small cost to each request that carries TempData. В противном случае поставщик TempData для состояния сеанса удобно использовать, чтобы устранить круговой обход большого объема данных в каждом запросе до полного использования TempData. If not, the session state TempData provider can be beneficial to avoid round-tripping a large amount of data in each request until the TempData is consumed.
    3. Приложение выполняется на ферме серверов на нескольких серверах? Does the app run in a server farm on multiple servers? Если это так, не требуется дополнительная настройка для использования поставщика TempData для файлов cookie, за исключением защиты данных (см. статьи Защита данных в ASP.NET Core и Key storage providers in ASP.NET Core (Поставщики хранилища ключей в ASP.NET Core)). If so, there’s no additional configuration required to use the cookie TempData provider outside of Data Protection (see Защита данных в ASP.NET Core and Key storage providers).

    Большинство веб-клиентов (например, веб-браузеры) налагают ограничение на максимальный размер каждого файла cookie и (или) общее количество таких файлов. Most web clients (such as web browsers) enforce limits on the maximum size of each cookie, the total number of cookies, or both. При использовании поставщика TempData на основе файлов cookie убедитесь, что приложение не нарушает эти ограничения. When using the cookie TempData provider, verify the app won’t exceed these limits. Учитывайте общий объем данных. Consider the total size of the data. Учитывайте увеличение размеров файла cookie в результате шифрования и фрагментирования. Account for increases in cookie size due to encryption and chunking.

    Настройка поставщика TempData Configure the TempData provider

    Поставщик TempData на основе файлов cookie включен по умолчанию. The cookie-based TempData provider is enabled by default.

    Чтобы включить поставщик TempData на основе сеанса, используйте метод расширения AddSessionStateTempDataProvider: To enable the session-based TempData provider, use the AddSessionStateTempDataProvider extension method:

    Порядок ПО промежуточного слоя важен. The order of middleware is important. В предыдущем примере исключение InvalidOperationException возникает при вызове UseSession после UseMvc . In the preceding example, an InvalidOperationException exception occurs when UseSession is invoked after UseMvc . Дополнительные сведения см. в разделе Порядок расположения ПО промежуточного слоя. For more information, see Middleware Ordering.

    Если вы ориентируетесь на .NET Framework и используете поставщик TempData на основе сеансов, добавьте в проект пакет Microsoft.AspNetCore.Session. If targeting .NET Framework and using the session-based TempData provider, add the Microsoft.AspNetCore.Session package to the project.

    Строки запроса Query strings

    Вы можете передать ограниченный объем данных из одного запроса в другой, добавив их в строку запроса нового запроса. A limited amount of data can be passed from one request to another by adding it to the new request’s query string. Это удобно для захвата состояния в сохраняемом виде, что позволяет обмениваться ссылками с внедренным состоянием по электронной почте или через социальные сети. This is useful for capturing state in a persistent manner that allows links with embedded state to be shared through email or social networks. Поскольку строки запроса URL-адреса являются открытыми, никогда не используйте их для конфиденциальных данных. Because URL query strings are public, never use query strings for sensitive data.

    Вдобавок к случайному раскрытию информации включение данных в строки запроса может открыть возможности для атак с подделкой межсайтовых запросов (CSRF), которые могут обманом вынудить пользователей посещать вредоносные веб-сайты во время проверки подлинности. In addition to unintended sharing, including data in query strings can create opportunities for Cross-Site Request Forgery (CSRF) attacks, which can trick users into visiting malicious sites while authenticated. Это позволит злоумышленникам похитить данные пользователей из приложения или предпринимать вредоносные действия от их имени. Attackers can then steal user data from the app or take malicious actions on behalf of the user. Любое сохраненное состояние приложения или сеанса необходимо защитить от атак CSRF. Any preserved app or session state must protect against CSRF attacks. Дополнительные сведения см. в статье Предотвращение атак с подделкой межсайтовых запросов (XSRF/CSRF). For more information, see Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks.

    Скрытые поля Hidden fields

    Данные можно сохранить в скрытых полях формы и опубликовать обратно при следующем запросе. Data can be saved in hidden form fields and posted back on the next request. Это типичное поведение для многостраничных форм. This is common in multi-page forms. Так как клиент может незаконно изменить данные, приложение всегда должно перепроверять данные в скрытых полях. Because the client can potentially tamper with the data, the app must always revalidate the data stored in hidden fields.

    HttpContext.Items HttpContext.Items

    Коллекция HttpContext.Items используется для хранения данных при обработке одного запроса. The HttpContext.Items collection is used to store data while processing a single request. Ее содержимое удаляется после обработки каждого запроса. The collection’s contents are discarded after a request is processed. Коллекцию Items часто используют для обеспечения взаимодействия компонентов или ПО промежуточного слоя, когда они выполняются в разные моменты времени во время обработки запроса и не могут передавать параметры напрямую. The Items collection is often used to allow components or middleware to communicate when they operate at different points in time during a request and have no direct way to pass parameters.

    В следующем примере ПО промежуточного слоя добавляет isVerified в коллекцию Items . In the following example, middleware adds isVerified to the Items collection.

    Далее в конвейере другое ПО промежуточного слоя может получить доступ к значению isVerified : Later in the pipeline, another middleware can access the value of isVerified :

    Для ПО промежуточного слоя, которое используется всего одним приложением, допустимы ключи string . For middleware that’s only used by a single app, string keys are acceptable. ПО промежуточного слоя, используемое несколькими экземплярами приложения, должно использовать уникальные ключи объекта во избежание конфликтов. Middleware shared between app instances should use unique object keys to avoid key collisions. В следующем примере показано, как использовать уникальный ключ объекта, определенный в классе ПО промежуточного слоя: The following example shows how to use a unique object key defined in a middleware class:

    Другой код может обратиться к значению, хранящемуся в HttpContext.Items , с помощью ключа, предоставляемого классом ПО промежуточного слоя: Other code can access the value stored in HttpContext.Items using the key exposed by the middleware class:

    Данный подход также позволяет не использовать строки ключей в коде. This approach also has the advantage of eliminating the use of key strings in the code.

    Кэш Cache

    Кэширование — это эффективный способ хранения и извлечения данных. Caching is an efficient way to store and retrieve data. Приложение может управлять временем существования элементов кэша. The app can control the lifetime of cached items.

    Кэшированные данные не связаны с конкретным запросом, пользователем или сеансом. Cached data isn’t associated with a specific request, user, or session. Будьте внимательны и не кэшируйте данные пользователя, которые можно извлечь по запросу другого пользователя. Be careful not to cache user-specific data that may be retrieved by other users’ requests.

    Дополнительные сведения можно найти по адресу: Кэширование ответов в ASP.NET Core. For more information, see Кэширование ответов в ASP.NET Core.

    Внедрение зависимостей Dependency Injection

    Используйте внедрение зависимостей, чтобы сделать данные доступными для всех пользователей: Use Dependency Injection to make data available to all users:

    Определите службу, содержащую данные. Define a service containing the data. Например, определяется класс с именем MyAppData : For example, a class named MyAppData is defined:


    Добавьте класс службы в Startup.ConfigureServices : Add the service class to Startup.ConfigureServices :

    Используйте класс службы данных: Consume the data service class:

    Распространенные ошибки Common errors

    «Unable to resolve service for type «Microsoft.Extensions.Caching.Distributed.IDistributedCache» while attempting to activate «Microsoft.AspNetCore.Session.DistributedSessionStore»» (Не удается разрешить службу для типа «Microsoft.Extensions.Caching.Distributed.IDistributedCache» при попытке активировать «Microsoft.AspNetCore.Session.DistributedSessionStore»). «Unable to resolve service for type ‘Microsoft.Extensions.Caching.Distributed.IDistributedCache’ while attempting to activate ‘Microsoft.AspNetCore.Session.DistributedSessionStore’.»

    Обычно она вызвана невозможностью настройки по меньшей мере одной реализации IDistributedCache . This is usually caused by failing to configure at least one IDistributedCache implementation. Дополнительные сведения см. в разделах Распределенное кэширование в ASP.NET Core и Кэширование в памяти в ASP.NET Core. For more information, see Распределенное кэширование в ASP.NET Core and Кэширование в памяти в ASP.NET Core.

    Если ПО промежуточного слоя для сеанса не удается сохранить сеанс (например, резервное хранилище недоступно), оно регистрирует исключение и запрос выполняется обычным образом. In the event that the session middleware fails to persist a session (for example, if the backing store isn’t available), the middleware logs the exception and the request continues normally. Это приводит к непредсказуемому поведению. This leads to unpredictable behavior.

    Например, пользователь сохраняет корзину для покупок в сеансе. For example, a user stores a shopping cart in session. Он добавляет товар в корзину, но фиксация завершается сбоем. The user adds an item to the cart but the commit fails. Приложению неизвестно о сбое, поэтому оно сообщает пользователю, что товар добавлен в корзину, хотя это не так. The app doesn’t know about the failure so it reports to the user that the item was added to their cart, which isn’t true.

    Лучшие практики для увеличения производительности ASP.NET Core приложений

    Всегда используйте последнюю версию ASP.NET Core и nuget пакетов

    Команда майкрософт активно обновляет ASP.NET и выпускает довольно таки значимые обновления, рекомендуем держать руку на пульсе и старатся обновлять библиотеки и саму версию ASP.NET, как только выходит новая.

    Примечание в статье часто используется понятие ‘Hot code path’. Под этим имеется ввиду место в вашем коде которое очень долго выполняется.

    Используйте кэширование

    Мы можем повысить производительность приложения, если сможем каждый раз уменьшать количество запросов к серверу. Это не означает, что вы не будете делать запросы на сервер вовсе, это только означает, что вы не будете делать запросы на сервер КАЖДЫЙ РАЗ. В первый раз вы сделаете запрос на сервер и получите ответ, и этот ответ будет храниться где-то на будущее в течение некоторого времени (конечное количество времени, например 90 минут), и в следующий раз, когда вы сделаете реквест на тот же эндпоинт, сначала вы проверите, если у вас уже есть данные которые где-то сохранены, и если да, то вы будете использовать сохраненные данные вместо того, чтобы делать вызов серверу.

    Кэширование бывает нескольких типов:

    Кэширование ответов на основе HTTP

    Устанавливается заголовком Cache-Control

    Распределенный кэш

    Используйте распределенный кэш для хранения данных к которым нужен быстрый доступ. Кэширование с помощью сторонних библиотек Например Redis Cache

    Кэширование в памяти

    Кэширование в памяти использует память сервера для хранения кэшированных данных. Этот тип кэширования подходит для одного или нескольких серверов.

    Cache Tag Helper

    Используйте cache tag helper в MVC приложениях, например:

    Distributed Cache Tag Helper

    Можно использовать Cache Tag Helper более широко и сохранять этот кэш например в Redis или SQL Server. В ASP.NET Core есть две встроенные реализации интерфейса IDistributedCache. Одна из них основана на SQL Server services.AddDistributedSqlServerCache , а другая — на Redis services.AddStackExchangeRedisCache.

    Redis Cache

    Когда мы работаем с редис кэшом. Мы это делаем скорее всего через самый популярный пакет StackExchange

    Для инициализации коннекшина мы вызываем такой код:

    Это может стать большой проблемой, если коннект был установлен быстро, вы не почуствуете разницу, но если ним были заминки и он может выполняться например около 30 секунд, блокируя наш поток. Для того чтобы так не происходило, необходимо использовать асинхронный код для этого:

    ResponseCache Атрибут

    Позволяет настроить для метода или класса параметры, необходимые для задания соответствующих заголовков в кэширование ответов (кэшировать или не, если да то на сколько кэшировать и др параметры)

    Профили кэша

    Вместо дублирования ResponseCache Атрибута, можно использовать кэш профиль, например:

    Всегда используйте асинхронное программирование и избегайте блокирующих запросов

    При разработке приложений ASP.NET Core старайтесь избегать создания блокирующих запросов. Блокирующий запрос означает запрос, который блокирует следующее выполнение, пока оно не будет завершено. Блокирующий запросили синхронный запросможет быть любым: либо вы извлекаете данные из API, либо выполняете некоторые внутренние операции. Вы должны всегда выполнять запрос в асинхронном режиме.

    Создавая ASP.NET Core приложение, вы должны его проектировать таким образом чтобы оно могло обрабатывать множество запросов одновременно. Асинхронные интерфейсы API позволяют использовать небольшой пул потоков для обработки тысяч одновременных запросов, не ожидая (как они это делают в синхронном программировании). Вместо того чтобы ожидать завершения выполнения синхронной задачи выполняющейся длительное время, поток может работать на другой запрос.

    Рекомендации:

    Х Не используйте:

    • Вызовы методов которые могут бликировать асинхронные вызовы путем выхова Task.Wait или Task.Result.
    • Избегайте блокировок на всех стадиях разработки приложения. ASP.NET Core спроектирован так чтобы выполнять все в асинхронном режиме.

    Используйте

    • Сделайте ‘hot code path’ места асинхронными.
    • Делайте запросы к Data access layer’y и долгим API операциям асинхронно.
    • Сделайте методы Контроллера асинхронными. Весь стек вызовов является асинхронным, это позволит вам использовать преимущества async/await шаблонов.

    Минимизируйте аллокации больших объектов

    Сборщик мусора .NET Core автоматически управляет распределением и освобождением памяти в приложениях ASP.NET Core. Автоматический сбор мусора обычно означает, что разработчикам не нужно беспокоиться о том, как или когда освобождается память. Однако очистка объектов, на которые нет ссылок, занимает процессорное время, поэтому разработчикам следует минимизировать распределение объектов в ‘hot code path’. Сборка мусора особенно дорога для больших объектов (> 85 Кбайт). Большие объекты хранятся в Large object heap объектов, и для их очистки требуется полная сборка мусора (поколение 2). В отличие от коллекций поколения 0 и поколения 1, коллекция поколения 2 требует временной приостановки выполнения приложения. Частое распределение и удаление больших объектов может привести к нестабильной производительности.

    Рекомендации:

    Х Не Создавайте много больших короткоживущих объектов в ‘hot code path.

    Используйте кэширование больших объектов, которые часто используются. Кэширование больших объектов предотвращает дорогие аллокации. Так же можно использовать один из классических паттернов Flyweight для работы с такими объектами.

    Используйте ArrayPool для хранения больших массивов.

    Использование класса ArrayPool для «аренды» и «возврата» буферов (с использованием методов Rent и Return) может повысить производительность в ситуациях, когда массивы часто создаются и уничтожаются, что приводит к значительному давлению памяти на сборщик мусора.

    Оптмизация Data Access Layer’a

    Эффективное чтение и запись данных очень важны для хорошей производительности.

    Рекомендации:

    Используйте асинхронные запросы к Data access layer’y.

    Используйте кэширование часто используемых данных, извлеченных из базы данных или удаленного сервиса (если это позволяет бизнес-логика). В зависимости от сценария используйте MemoryCache или DistributedCache. Для дополнительной информации см. раздел «Используйте кэширование».

    Минимизируйте количество запросов для получения данных (цель получить данные за один запрос, не делая несколько запросов)

    Используйте фильтрацию и агрегирование запросов LINQ (например, с помощью операторов .Where, .Select или .Sum), чтобы фильтрация выполнялась базой данных.

    Х Не запрашивайте больше данных, чем неободимо. Ваши запросы должны вернуть только те данные. которые необходимы для текущего HTTP-запроса

    Х Избегайте больше N + 1 проблемы

    Пул HTTP-подключений с HttpClientFactory

    Несмотря на то что HttpClient реализует интерфейс IDisposable, он предназначен для повторного использования. Закрытые экземпляры HttpClient оставляют сокеты открытыми в состоянии TIME_WAIT на короткое время. Если часто используется класс, который создает и удаляет объекты HttpClient, приложение может исчерпать доступные сокеты. HttpClientFactory был введен в ASP.NET Core 2.1 как решение этой проблемы. Он обрабатывает пул HTTP-соединений для оптимизации производительности и надежности.

    Стремитесь к быстродействию в коде который вы используете в middleware

    Запускайте код который выполняется длительное время за пределами HTTP реквестов

    Большинство запросов к приложению ASP.NET Core могут обрабатываться контроллером или моделью страницы, вызывая необходимые сервисы и возвращая HTTP-ответ. Для некоторых запросов, которые включают в себя длительные задачи, лучше сделать весь процесс запрос-ответ асинхронным.

    Рекомендации:

    Х Избегайте ожидания завершения длительных задач как части обычной обработки HTTP-запроса.
    Используйте обработку долго-выполняющихся запросов с помощью фоновых служб (например Azure function, AWS Lambda, и тд). Завершение работы вне процесса особенно полезно для задач с интенсивным использованием процессора.
    Используйте тулы такие как SignalR, для асинхронной связи с клиентами в режиме реального времени.

    Минифицируйте client assets и используйте сжатие ответов с сервера

    Приложения ASP.NET Core интерфейсами часто обслуживают множество файлов JavaScript, CSS или изображений. Производительность при «initial load» может быть улучшена за счет:

    • Bundling и минификация (лучше всего на данный момент использовать WebPack для этих целей).
    • Используйте CDN
    • Ужимайте картинки
    • Используйте Gzip для ответов с сервера

    Код который блокирует потоки

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

    Установим его с Nuget’a

    И вызываем метод в нашем IApplicationBuilder

    Asp избегайте кэшировать медленные компоненты в объектах application или session

    Евгений Смолин: Сам кувыркался с непонятками (пока курсы учебные не прочитал и руками не попробовал то, что там написано). Битрикс из тех систем, где изучение «методом тыка» не очень эффективно без предварительного изучения учебных курсов. Уважаемые новички, потратьте немного своего драгоценного времени, пройдите пару-тройку учебных курсов и масса вопросов просто испарится — там есть ответы на множество вопросов.

    Курс для разработчиков — продолжение линейки учебных курсов по Bitrix Framework. Получение сертификата по курсу рекомендуется после успешной сдачи тестов по всей линейке курсов, так как без понятия о работе Контент-менеджера и Администратора создание успешных сайтов будет затруднено.

    Чтобы научиться программировать в Bitrix Framework, нет необходимости изучать всю линейку курсов. Но есть моменты, которые необходимо знать разработчикам о системе, они раскрыты в начальных курсах:

    • Интерфейс программы — в главе Элементы управления курса Контент-менеджер.
    • Компоненты 2.0 (начальные сведения) в главе Компоненты 2.0 (начальные сведения) курса Контент-менеджер.
    • Информационные блоки — в главе Информационные блоки (начальные сведения) курса Контент-менеджер.
    • Управление доступом к файлам, элементам контента, модулям и другие права доступа в главе Управление доступом курса Администратор. Базовый.
    • Работа с инструментами системы — в главе Работа с инструментами курса Администратор. Базовый.
    • Модуль Поиск — в главе Поиск курса Администратор. Базовый.
    • Вся информация по администрированию модулей размещена в курсах:
      • Администрирование. Модули — модули «1С-Битрикс: Управление сайтом»
      • Администратор. Бизнес — модули «1С-Битрикс: Управление сайтом», связанные с коммерческой деятельностью в Интернете.
      • Администратор «1С-Битрикс: Корпоративный портал» — модули «1С-Битрикс: Корпоративный портал»

      По завершению изучения этого курса можно продолжить изучение работы в продуктах Bitrix Framework по следующим курсам:

    • Бизнес-процессы — настройка и создание бизнес-процессов.
    • Бот платформа Битрикс24 — приложения, основанных на чатах в веб-мессенджере.
    • Маркетплейс Битрикс24 — приложения для коробочной и облачной версий Битрикс24.
    • Маркетплейс Bitrix Framework — расширение функционала проектов на основе Bitrix Framework с помощью сторонних модулей и решений.
    • Многосайтовость — система многосайтовости и принципы работы с многосайтовой конфигурацией.


    Начальные требования к подготовке

    Для успешного изучения курса и овладения мастерством разработки сайтов на Bitrix Framework необходимо владеть (хотя бы на начальном уровне):

    • основами PHP, баз данных;
    • основами HTML, CSS.

    После изучения курса вам будет предложено пройти тесты на сертификацию. При успешной сдаче последовательности тестов на странице Моё обучение можно просмотреть результат обучения и загрузить сертификат в формате PDF.

    На каждой странице курса авторизованный на сайте посетитель может дать комментарий к содержимому страницы. Комментарий — не форум, там не ведётся обсуждений или разъяснений. Это инструмент для сообщений нам об ошибках, неточностях. Для отправки комментария воспользуйтесь расположенной в правом нижнем углу окна браузера кнопкой:

    Для преподавания оффлайн

    Если данный курс берётся в качестве основы для оффлайного преподавания, то рекомендуемая продолжительность: 5 дней (40 академических часов).

    Примечание: В тексте курса вы встретите цитаты, высказанные в разное время разработчиками системы и разработчиками проектов на базе Bitrix Framework. Надеемся, что такие неформальные замечания внесут некоторое разнообразие в процесс изучения. Заодно опытные специалисты поделятся и своим опытом.

    Имена авторов цитат даются в том написании, в каком авторы зарегистрировали себя на сайте «1С-Битрикс».

    Скачать материалы курса в формате CHM. Файлы формата CHM обновляются ежемесячно, тем не менее, возможно некоторое отставание их от онлайновой версии курса.

    Чтобы отключить подобное отношение к файлу необходимо:

      перейти в свойства файла на вкладку Общие. Внизу у Вас отобразится сообщение о том, что этот файл был заблокирован системой с целью защиты компьютера.

    Отсутствие кнопки Разблокировать возможно в двух случаях:

    1. Файл лежит не локально, а на сетевом ресурсе.
    2. Если файл лежит на локальном диске, но путь к нему содержит спецсимволы (# и прочие).

    Кэширование

    Кэширование с помощью MemoryCache

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

    Кэширование в ASP.NET Core построено вокруг зависимости Microsoft.Extensions.Caching.Memory и предполагает использование встроенного инструмента кэширования — объекта IMemoryCache .

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

    Для решения этой задачи создадим проект ASP.NET Core по типу Web Application (Model-View-Controller) . Пусть он будет называться CachingMVC . Взаимодействовать с базой данных мы будем через Entity Framework.

    Весь основной функционал по работе с кэшированием заключен в NuGet-пакете Microsoft.Extensions.Caching.Memory , который по умолчанию уже добавлен в проекты ASP.NET Core версии 2.0 и выше.

    Вначале добавим в проект в папку Models новый класс Product, который будет описывать используемые данные:

    И также добавим в папку Models класс контекста данных:

    Для взаимодействия с контекстом и бд создадим специальный сервис. Для этого вначале добавим в проект папку Services и в ней определим новый класс ProductService:

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

    Через встроенный механизм внедрения зависимостей в конструкторе мы можем получить объект кэша IMemoryCache. Применяя методы интефейса IMemoryCache, мы можем управлять кэшем:

    bool TryGetValue(object key, out object value) : пытаемся получить элемент по ключу key. При успешном получении параметр value заполняется полученным элементом, а метод возвращает true

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

    void Remove(object key) : удаляет из кэша элемент по ключу key

    object Set(object key, object value, MemoryCacheEntryOptions options) : добавляет в кэш элемент с ключом key и значением value, применяя опции кэширования MemoryCacheEntryOptions

    По сути встроенная реализация интерфейса IMemoryCache — класс MemoryCache, который используется по умолчанию, инкапсулирует все объекты кэша в виде словаря Dictionary.

    Здесь же кэширование реализуется в двух случаях: при получение объкта по id из бд и при добавлении этого объекта.

    При добавлении объект вначале добавляется в базу данных, и в случае удачного добавления, также добавляется в кэш:

    При сохранении объекта в кэше в качестве его ключа выступает значение свойства Id.

    С помощью параметра AbsoluteExpirationRelativeToNow здесь устанавливатся время кэширования — 5 минут.

    При получении объекта по id вначале пытаемся найти этот объект в кэше, и если там не оказалось, то извлеаем его и бд и затем добавляем в кэш.

    Если ключ в кэше был найден, то в объект product передается извлекаемое из кэша значение, а метод TryGetValue() возвращает true. Для установки времени кэширования здесь применяется альтернативный способ — метод SetAbsoluteExpiration, который в данном случае таже устанавливает 5 минут.

    В данном случае ключом выступает строка «BestSeller». Этому ключу будет соответствовать полученный из базы данных объект Phone. В принципе мы можем сохранить в базу данных любой объект.

    Если ключ в кэше был найден, то в объект phone передается извлекаемое из кэша значение, а метод TryGetValue() возвращает true.

    Если же метод возвращает false, значит ключ не найден, и нам надо извлечь объект Phone из базы данных и поместить в кэш:

    В данном случае кэширование будет идти 5 минут.

    В итоге у нас получится следующая структура проекта:

    Если бы использовали фреймворк MVC, то фактически все действия компонента middleware по кэшированию мы могли бы перенести в контроллер и также его использовать.

    Затем нам надо зарегистрировать сервисы кэширования и entity framework и применить компонент m >Startup :

    Прежде всего для добавления возможности кэширования нам надо добавить сервис в методе ConfigureServices() :

    По сути этот сервис устанавливает зависимость для IMemoryCache, создавая объект синглтон:

    И в классе контроллера HomeController определим следующий код:

    В итоге при первом обращении к приложению данные будут извлекаться из базы данных и сохраняться в кэш. При всех последующих обращениях в пределах времени кэширования (в данном случае в течение 5 минут) данные будут извлекаться из кэша:

    Кеширование в ASP.NET MVC

    В прошлом посте я рассказывал о различных стратегиях кеширования. Там была голая теория, которая и так всем известна, а кому неизвестна, тому без примеров ничего не понятно.

    В этом посте я хочу показать пример кеширования в приложении ASP.NET MVC и какие архитектурные изменения придется внести, чтобы поддерживать кеширование.

    Для примера я взял приложение MVC Music Store, которое используется в разделе обучение на сайте asp.net. Приложение представляет из себя интернет-магазин, с корзиной, каталогом товаров и небольшой админкой.

    Исследуем проблему

    Сразу создал нагрузочный тест на одну минуту, который открывает главную страницу. Получилось 60 страниц в секунду (все тесты запускал в дебаге). Это очень мало, полез разбираться в чем проблема.

    Код контроллера главной страницы:

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

    При этом в каждой странице выводится персонализированная информация — количество элементов в корзине.
    Код _layout.cshtml (Razor):

    Такой «паттерн» часто встречается в веб-приложениях. На главной странице, которая открывается чаще всего, выводится в одном месте статистическая информация, которая требует больших затрат на вычисление и меняется нечасто, а в другом месте — персонализированная информация, которая часто меняется. Из-за этого главная страница работает медленно, и средствами HTTP её кешировать нельзя.

    Делаем приложение пригодным для кеширования

    Чтобы такой ситуации, как описано выше, не происходило надо разделить запросы и собирать части страницы на клиенте. В ASP.NET MVC это сделать довольно просто.
    Код _layout.cshtml (Razor):

    В коде контроллера:

    Установка режима кеширования NoCache необходима, так как браузеры могут по умолчанию кешировать Ajax запросы.

    Само по себе такое преобразование делает приложение только медленнее. По результатам теста — 52 страницы в секунду, с учетом ajax запроса для получения состояния корзины.

    Разгоняем приложение

    Теперь можно прикрутить lazy кеширование. Саму главную страницу можно кешировать везде и довольно долго (статистика терпит погрешности).
    Для этого можно просто навесить атрибут OutputCache на метод контроллера:

    Чтобы оно успешно работало при сжатии динамического контента необходимо в web.config добавить параметр:

    Это необходимо чтобы сервер не отдавал заголовок Vary:*, который фактически отключает кеширование.

    Нагрузочное тестирование показало результат 197 страниц в секунду. Фактически страница home\index всегда отдавалась из кеша пользователя или сервера, то есть настолько быстро, насколько возможно и тест померил быстродействие ajax запроса, получающего количество элементов в корзине.

    Чтобы ускорить работу корзины надо сделать немного больше работы. Для начала результат cart.GetCount() можно сохранить в кеше asp.net, и сбрасывать кеш при изменении количества элементов в корзине. Получится в некотором роде write-through кеш.

    В MVC Music Store сделать такое кеширование очень просто, как так всего 3 экшена изменяют состояние корзины. Но в сложном случае, скорее всего, потребуется реализации publish\subscribe механизма в приложении, чтобы централизованно управлять сбросом кеша.

    Метод получения количества элементов:

    В методы, изменяющие корзину, надо добавить две строчки:

    В итоге нагрузочный тест показывает 263 запроса в секунду. В 4 раза больше, чем первоначальный вариант.

    Используем HTTP кеширование

    Последний аккорд — прикручивание HTTP кеширование к запросу количества элементов в корзине. Для этого нужно:

    1. Отдавать Last-Modified в заголовках ответа
    2. Обрабатывать If-Modified-Since в заголовках запроса (Conditional GET)
    3. Отдавать код 304 если значение не изменилось

    Начнем с конца.
    Код ActionResult для ответа Not Modified:

    Добавляем обработку Conditional GET и установку Last-Modified:

    Конечно такой код в production писать нельзя, надо разбить на несколько функций и классов для удобства сопровождения и повторного использования.

    Итоговый результат на минутном забеге — 321 страница в секунду, в 5,3 раза выше, чем в первоначальном варианте.

    Является ли кэширование с использованием приложения более медленным или более проблематичным, чем использование статической переменной Global.asax.cs?

    У нас есть приложение Webforms, в котором хранится множество настроек и терминологических сопоставлений (несколько сотен), которые используются во всем приложении.

    Коллекция Application [] может быть медленнее и сложнее.

    объект Application []. неэффективен в ASP.NET.

    Это рекомендуется? Да, а не только автором этой статьи. Это отмечено в Professional ASP.NET от Apress и многих сайтах в Интернете. Это работает хорошо

    Поэтому мне интересно, верны ли эти утверждения. Может ли кто-нибудь объяснить, почему использование приложения медленнее или какие проблемы могут возникнуть, если вы используете приложение? Я вроде бы предполагаю, что любые проблемы или замедление могут возникать только при производственных нагрузках, поэтому я прошу об опыте реального мира, а не просто тестировании себя.

    Я знаю, что существует много альтернатив кешированию (HttpRuntime.Cache, memcached и т.д.), Но я хочу знать, нужно ли мне вернуться и переписать старый код, использующий Application []. В частности, если я каким-либо образом подвергаюсь штрафу за исполнение, я бы хотел избавиться от этого.

    Как вы сохраняете эти настройки? Я бы порекомендовал web.config

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

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

    Кроме того, переменные в файлах web.config/app.config могут изменяться без изменения кода и/или перекомпиляции вашего проекта.

    Класс приложения (глобальные переменные) существует только в ASP.NET, чтобы помочь с обратной совместимостью с классическим ASP, вы можете сказать, что он устарел.

    Еще одна вещь, которую вы могли бы изучить, — это кэширование ваших настроек, чтобы вы не всегда читали с диска.

    Илон Маск рекомендует:  КОММЕРЧЕСКАЯ ТАЙНА. ЗАЩИТА ОТ ИЗЪЯТИЯ
  • Понравилась статья? Поделиться с друзьями:
    Кодинг, CSS и SQL