Asp разработка масштабируемых asp приложений


Содержание

Библиотека Интернет Индустрии I2R.ru

Малобюджетные сайты.

Продвижение веб-сайта.

Контент и авторское право.

Компоненты ASP. Службы COM+ в ASP-компонентах и ASP-приложениях

Создавать и успешно использовать ASP-компоненты можно и без прямого обращения к каким-либо службам COM+. Однако именно эти службы могут внести ту «изюминку», которая превратит просто удовлетворительно работающее ASP-приложение в хорошо масштабируемое и соответствующее предъявляемым ему требованиям, независимо от того, каковы эти требования.

Службы COM+, к которым, прежде всего, стоит обратиться в разработке ASP-компонентов, — это управление транзакциями (transaction management), активация по требованию (just-in-time activation, JIT) и резервирование (pooling). Кроме того, можно использовать новые интерфейсы, которые были созданы для поддержания большей части возможностей этих служб. Однако перед рассмотрением всех этих новшеств обратимся к применению компонентов в приложениях.

Разработка систем на основе компонентов

Именно система, построенная на основе компонентов, выделяет индивидуальные процессы в многократно используемые порции кода и данных, а затем использует один или несколько этих компонентов для сознания полноценных приложений. Среди нескольких типов приложений различают клиент-серверную (client/server), распределенную (distributed) и многоярусную (n-tier) системы. В клиент-серверной системе (client-server system) процессы распределяются между клиентом и сервером, причем клиент отвечает за все взаимодействия с пользователем, отображение данных и подтверждение полномочий клиента, а сервер обрабатывает большую часть обращений к базам данных, проверяет полномочия сервера и контролирует бизнес-правила. В распределенной системе (distributed system) компоненты приложений могут располагаться на разных машинах и географически находиться в разных местах. Кроме того, для обработки множественных запросов может быть создано несколько экземпляров одного и того же компонента, таким образом, появляется возможность предоставлять одну и ту же услугу сразу множеству клиентов. И наконец, многослойная система (n-tier system) объединяет в себе элементы как клиент-серверной, так и распределенной систем. Здесь, как и в клиент-серверной системе, присутствует иерархия компонентов, однако сами по себе компоненты могут дублироваться для распределения загрузки процессов, а также распределяться на большом количестве машин и мест, как это происходит в распределенной системе. Стандартная n-ярусная система может состоять из клиента, выполняющего все взаимодействия с пользователем, проверку полномочий клиента и отображение данных; бизнес-уровня, контролирующего бизнес-правила, общие вопросы управления транзакциями и проверку полномочий, и уровня данных, обрабатывающего все прямые обращения к данным.

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

Другим преимуществом компонентов является тот факт, что гораздо больше родовых функций (generic functions) может быть разделено на отдельные компоненты и, таким образом, использовано во всей системе. Кроме того, применение компонентов упрощает модель и конструкцию n-ярусной системы. В качестве примера можно привести систему, в которой интерфейсный компонент проверяет достоверность адресной информации. Проверка достоверности достаточно характерна: она просто подтверждает тот факт, что все необходимые поля, такие как «Город» или «Почтовый индекс», заполнены. Тогда бизнес-уровень сможет обрабатывать для приложения адресную информацию, исходя из типа бизнеса. На основе адресной информации бизнес-уровень может вести поиск, например, зон отгрузки для компонента с помощью соответствующего приложения или зон доставки для виртуальной системы заказов. Компонент может обратиться к уровню данных для сохранения адресной информации, извлечения дополнительной информации или даже для запуска других виртуальных бизнес-компонентов, выполняющих какую-либо еще обработку информации. Уровень данных сам по себе может быть разделен по отдельным машинам, отдельным базам данных или даже различным типам хранилищ данных, вместе с некоторой информацией, идущей на долговременное или кратковременное хранение (если информация может потребоваться лишь в некоторой специфической задаче, а затем должна быть удалена).

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

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

В Windows 2000 работа с компонентами существенно облегчается службами COM+, выполняющими для компонентов такие действия, как например резервирование и транзакции. Именно для реализации этих задач традиционные интерфейсы COM были дополнены совершенно новыми интерфейсами, о которых вы узнаете в следующем разделе.

Интерфейсы COM+

Большинство важнейших интерфейсов COM, таких как, например, IUnknown и IDispatch, с появлением среды COM+ не претерпело каких-либо изменений и по сию пору решает все те же знакомые нам задачи. Главное отличие между COM и COM+ состоит в том, что та функциональность, которая в Windows NT и Windows 98 выполнялась средствами MTS, нынче полностью интегрирована в архитектуру COM+. Такого рода интеграция не только принесла с собой новые возможности, предоставляемые службами COM+, но и позволила существенно улучшить характеристики компонентов.

Разумеется, разработчики COM+ не забыли о необходимости поддержки новых служб COM+, а также нескольких новых интерфейсов уже имеющимися средствами, реализованными в MTS. В следующих нескольких разделах нами будут рассмотрены несколько ключевых интерфейсов, без знания которых, как нам кажется, разработка ASP-компонентов была бы бессмысленна.

Интерфейс IObjectContext

В главе 4 мы обсуждали концепцию контекстов (contexts) как совокупностей объектов, отвечающих одинаковыми требованиями. Среди таких требований может быть, например, возможность резервирования (pooling) для компонентов или их совместное участие в транзакциях.

В Windows 2000 контекст компонентов представляет собой набор свойств времени выполнения (runtime properties), непосредственная работа с которым может вестись с помощью объекта ObjectContext, управляющего контекстной информацией для компонента. Для доступа к свойствам объекта ObjectContext используется интерфейс IObjectContext, доступный, в свою очередь, с помощью библиотеки типов служб COM+.

Ответ на вопрос о том, каким именно образом осуществляется доступ к объекту ObjectContext, зависит от того, каким языком программирования вы пользуетесь. Например, если взять Visual Basic, то здесь сначала производится импорт ссылки на библиотеку типов служб COM+ в рабочий проект, и только потом можно создать ссылку на объект ObjectContext и вызвать для создания экземпляра метод GetObjectContext:

Dim objContext As ObjectContext
Set objContext = GetObjectContext

В Visual С++ под Windows NT для доступа к объекту ObjectContext также можно применить метод GetObjectContext:

CComPtr m_spObjectContext;
hr = GetObjectContext(&m_spObjectContext);

В то же время, в Visual C++ под Windows 2000 для передачи интерфейсу идентификатора GUID уже используется метод CoGetObjectContext:

hr = CoGetObjectContext(IID_IObjectContextInfo,
(void **)&m_spObjectContext);

Независимо от того, применяется ли метод GetObjectContext или метод CoGetObjectContext, результаты будут одними и теми же, поскольку вызов метода CoGetObjectContext в COM+ является оболочкой для вызова метода GetObjectContext. В Visual С++ придется также добавить в путь библиотеки компонента ссылку на заголовочный файл comsvcs.h служб COM+ и ссылку на файл связанного объекта comsvcs.lib.

Получив ссылку на интерфейс IObjectContext, можно вызывать его методы, перечисленные в табл. 1.

табл. 1. Методы интерфейса IObjectContext

Метод Описание
CreateInstance Создает экземпляр объекта
DisableCommit Показывает, что компонент не готов к выполнению транзакции
EnableCommit Показывает, что компонент все еще обрабатывается, но транзакция может быть выполнена
IsCallerInRole Показывает, соответствует ли вызывающий определенной роли (с учетом ролевой безопасности)
IsInTransaction Показывает, участвует ли компонент в транзакции
IsSecurityEnabled Показывает, включена ли защита
SetAbort Показывает, что компонент завершил работу и транзакция прервана
SetComplete Показывает, что компонент завершил работу и транзакция готова к принятию

Интерфейс обладает следующими свойствами:

  • ContextInfo — возвращает ссылку на объект контекстной информации, связанный с компонентом;
  • Count — показывает число именованных свойств объекта;
  • Item — содержит имена свойств;
  • Security — возвращает ссылку на объект Security, связанный с объектом ObjectContext.

Интерфейс информации контекста IObjectContextInfo более подробно будет рассмотрен в следующем разделе. Для обращения к встроенным ASP-объектам применяется коллекция Item. Получить доступ к ней можно непосредственно из Visual Basic:

Dim oc As ObjectContext
Dim app As Application
Set oc = GetObjectConext
Set app = oc.Item(«Application»)

Получить доступ к ASP-объектам можно и через объект ObjectContext:

Set app = oc(«Application»)

Из других программных языков для обращения к объектам ASP придется применить другие технологии. В C++, например, для получения доступа к определенному ASP-объекту нужно послать запрос экземпляру интерфейса IGetContextProperties:

CComPtr pProps; //свойства контекста

//получение ObjectContext
hr = CoGetObjectContext(IID_IObjectContext,
(void **)&m_spObjectContext);
if (FAILED(hr)) return hr;

//получение свойств контекста
hr = m_spObjectContext ->
QueryInterface( IID_IGetContextProperties,
(void**)&pProps );
if (FAILED(hr)) return hr;

получение свойства Response
bstrProp = «Response»;
hr = pProps->GetProperty( bstrProp, &vt ) ;
if (FAILED(hr)) return hr;

p > hr = piDispatch->QueryInterface( IID_IResponse,
(void**)&m_piResponse );

В документации к интерфейсу IGetContextProperties сообщается, что он действует только в среде Windows NT, но и в Windows 2000 с его помощью также можно обращаться к встроенным ASP-объектам.

Интерфейс IObjectContextInfo

Интерфейс IObjectContextInfo служит для получения относящейся к текущему компоненту информации о транзакциях, активности и контексте. С помощью этого интерфейса можно получить доступ к указателю на интерфейс ITransaction. В табл. 2 приведены методы интерфейса IObjectContextInfo.

табл. 2. Методы интерфейса IObjectContextInfo

Метод Описание
GetActivityId Возвращает идентификатор текущей активности
GetContextId Возвращает идентификатор текущего контекста
GetTransaction Возвращает указатель на интерфейс ITransaction
GetTransactionId Возвращает идентификатор текущей транзакции
IsInTransaction Показывает, участвует ли компонент в транзакции

Если в компонентах COM+ осуществляется синхронизация (описываемая позже), метод GetActivityId возвращает идентификатор текущей активности, в противном случае будет возвращено значение Null.

Метод GetTransaction возвращает указатель на интерфейс ITransaction. С помощью этого интерфейса можно принять или прервать транзакцию, хотя реализуются эти функции с помощью объекта ObjectContext или интерфейса IContextState, рассматриваемых далее.

Интерфейс IContextState

Интерфейс IContextState предоставляет возможность более четкого управления транзакциями и активацией, чем это допустимо в интерфейсе IObjectContext. Например, в интерфейсе IObjectContext с помощью метода SetComplete можно отметить компонент, как завершивший работу и ожидающий принятия транзакции, а с помощью метода SetAbort отметить его как завершивший работу и ожидающий прерывания текущей транзакции.

На практике есть два условных бита, устанавливаемых при работе с методами SetComplete и SetAbort. Первый из их — бит завершения (done bit), его установка указывает COM+, что обработка компонента завершена. Второй — бит согласованности (consistency bit). Установка этого бита определяет, может ли быть транзакция принята или она должна быть прервана.

Оба метода, SetComplete и SetAbort, интерфейса IObjectContext одновременно устанавливают оба бита, причем оба устанавливают бит завершения в значение True, указывая, что обработка компонента завершена. В то же время, с помощью интерфейса IContextState можно идентифицировать факт окончания работы компонента отдельно от статуса транзакции.

В табл. 3 приведены четыре метода интерфейса IContextState.

табл. 3. Методы интерфейса IContextState

Метод Описание
GetDeactivateOnReturn Получает состояние бита завершения
GetMyTransactionVote Получает состояние бита согласованности
SetDeactivateOnReturn Сигнализирует о завершении работы компонента
SetMyTransactionVote Идентифицирует возможность принятия либо прерывания транзакции

Бит завершения можно получать и устанавливать с помощью методов SetDeactivateOnReturn и GetDeactivateOnReturn. Компонент деактивируется по завершении методов только при значении бита завершения, установленном в True.

Чтобы убедиться во всех этих возможностях, создайте компонент Visual Basic, реализующий для перехвата событий JIT интерфейс IObjectControl. (Интерфейс IObjectControl подробно описывается в следующем разделе.) У этого метода будет два компонента, каждый из которых вызывает метод SetDeactivateOnReturn интерфейса IContextState. Первая функция будет вызывать метод, передавая логическое значение False, вторая — True.

Создайте проект Visual Basic и назовите его asp0501, а класс генерируемого компонента — done. Присоедините к проекту библиотеки типов служб COM+ и Microsoft Active Server Pages. Коль скоро библиотеки типов добавлены как ресурсы, реализуйте, как показано в листинге 5.1, JIT-методы Activate, Deactivate и CanBePooled интерфейса IObjectControl.

Листинг 1. Реализация JIT-функций интерфейса IObjectControl

Dim objResponse As Response

Private Sub ObjectControl_Activate()
Set objResponse = GetObjectContext().Item(«Response»)
objResponse.Write «

Активирован

Private Sub ObjectControl_Deactivate()
objResponse.Write «

Деактивирован

Private Function ObjectControl_CanBePooled() As Boolean
ObjectControl_CanBePooled = False
End Function

В методе Activate созданная ссылка на встроенный ASP-объект Response используется для отображения сообщения о том, что метод активирован. В методе Deactivate на web-страницу выводится сообщение о том, что компонент деактивирован.

Далее, добавьте две функции компонента, вызываемые ASP-страницей. Первая, под именем function1, обращается к интерфейсу IContextState и вызывает его метод SetDeactivateOnReturn, передавая значение False. Вторая функция, function2, также вызывает метод SetDeactivateOnReturn, но на сей раз передается значение True. В листинге 5.2 приведен программный код обеих функций, который и нужно добавить к нашему компоненту.

Листинг 2. Подпрограммы, вызывающие метод SetDeactivateOnReturn

Dim iCntxt As IContextState
Set iCntxt = GetObjectContext

iCntxt.SetDeactivateOnReturn False
End Sub

Dim iCntxt As IContextState
Set iCntxt = GetObjectContext

iCntxt.SetDeactivateOnReturn True
End Sub

После того как проект компонента скомпилирован и добавлен к приложению COM+, протестируйте новый компонент с помощью ASP-сценария примерно такого содержания (как в странице asp0501.asp):

Первой вызывается функция function2, деактивирующая компонент при возвращении значения функцией. Благодаря этому при обращении к функции компонента будет отображаться сообщение «Активирован», а при возвращении функцией значения будет отображаться сообщение «Деактивирован» еще до сообщения «Вызов function 1».

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

Наконец, при повторном вызове функции function2, должны быть отображены оба сообщения, «Активирован» и «Деактивирован», при этом генерируется web-страница со следующими сообщениями:

Вызов function 2

Вызов function 1

Вызов function 2

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

Интерфейс IObjectControl

В этом разделе показано, как можно управлять временем жизни (lifetime) компонента с помощью интерфейса IContextState. В примере также используется активация по требованию (just-in-time activation, JIT) — для управления созданием экземпляра компонента и записи на web-страницу с помощью методов Activate и Deactivate интерфейса IObjectControl сообщений об активации и деактивации компонента.

Разрешение активации по требованию компонента означает, что компонент активируется, только когда он реально требуется, а не при первоначальном создании на ASP-странице. Кроме того, компонент деактивируется, только когда он помечается как готовый к деактивации, удаляется внутри ASP-страницы (например, установлен в Nothing, если вы работаете с VBScript) или процесс выходит за пределы страницы.

Процесс активации и деактивации управляется COM+ с помощью программных ключей, указываемых разработчиками, как, например, тот, что показан в этом разделе для вызова метода SetDeactivateOnReturn интерфейса IContextState.

Как разработчик компонента, вы можете перехватывать моменты активации и деактивации компонента путем реализации методов Activate и Deactivate интерфейса IObjectControl. В этом случае вы не зависите от ресурсов (типа ссылки на объект Response в листинге 5.1) в период простоя компонента и ожидания вызова его методов.

При реализации интерфейса IObjectControl вы должны реализовать и методы Activate и Deactivate — а кроме того, еще и метод CanBePooled. Этот последний метод определяет, находится ли компонент в состоянии, когда он может быть резервирован (pooled). Позднее в этой главе при описании служб COM+ мы рассмотрим резервирование (pooling) компонентов более подробно.

Чтобы воспользоваться преимуществами активации по требованию, компонент должен быть установлен в приложение COM+, а активация по требованию разрешена. Впрочем, поддержка активации по требованию в приложении COM+ для всех компонентов включена по умолчанию.

Интерфейсы IObjectControl и IObjectContext были реализованы в Windows NT и управляются посредством MTS. Фактически же, ASP-компоненты, созданные для Windows NT, за исключением использующих специфические службы NT, можно без проблем перенести на Windows 2000 и COM+, что и обсуждается в следующем разделе.

ПРИМЕЧАНИЕ
В Windows NT приходилось избегать применения обработчиков событий Initialize и Terminate, поскольку они не позволяли обратиться к экземпляру объекта ObjectContext. Это ограничение в Windows 2000 снято. И все же, по-прежнему важно рассмотреть реализацию интерфейса IObjectControl и перехват (trapping) событий Activate и Deactivate для обеспечения доступа к глобальным ресурсам и их высвобождения.

Перенос пакетов MTS в приложения COM+

В Windows NT (or Windows 9x) компонентами можно было управлять как частью пакетов (packages) MTS. Будучи частью пакета MTS, компонент мог воспользоваться некоторыми возможностями MTS, например, выполнением транзакций и активацией по требованию. Те же и многие другие возможности доступны также и в COM+, и обратиться к ним из существующих компонентов можно, перенеся в новую среду пакеты MTS, компоненты или то и другое.

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

Можно относительно просто перенести пакеты MTS в COM+, создав с помощью консоли служб компонентов (Component Services Console) новое приложение COM+ и установив переключатель Install Pre-built Application(s) (Установить готовое приложение). Когда мастер установки приложения COM (COM Application Install Wizard) запросит имя существующего приложения, найдите или выберите созданный ранее PAK-файл.

При импорте существующего пакета MTS в новое приложение COM+ диспетчер служб компонентов (Component Services Manager) импортирует также роли (roles) и пытается сопоставить существующую функциональность MTS новой функциональности служб COM+ — включая настройки транзакций и активации по требованию.

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

В следующем разделе обсуждаются некоторые настройки приложений COM+, влияющие на ASP-приложения.

СОВЕТ
За дополнительной информацией о работе с консолью служб компонентов (Component Services Console) обратитесь к справочной системе Windows 2000.

Активация приложений COM+

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

ПРИМЕЧАНИЕ
В этом разделе рассмотрены не все возможные службы COM+, а лишь самые необходимые для разработки ASP-компонентов, например, безопасность, транзакции и объединение объектов. Активация по требованию подробно рассмотрена в разделе «Интерфейс IObjectControl».

Управлять безопасностью ASP-приложения на уровне страницы или ресурса можно с помощью средств безопасности NTFS или средств безопасности IIS. С помощью средств ролевой безопасности приложений COM+ можно добавить и еще один уровень безопасности.

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

Приложение COM+ можно создать по двум различным схемам активации: активации внутри клиентского процесса и активации в изолированном процессе.

Если приложение COM+ создано как серверное, обращение к компоненту с ASP-страницы генерирует отдельную программу dllhost.exe для этого компонента и любого другого, являющегося частью приложения COM+. Поскольку компонент находится в отдельном процессе, все вызовы компонента с ASP-страницы должны маршализироваться. Вместе с тем, если компонент некачественный и генерирует нечто опасное для программного обеспечения, это нечто останется внутри файла dllhost.exe и не сможет неблагоприятно повлиять на IIS или остальные ASP-приложения.

Если создать приложение COM+ как библиотечное, при обращении к компоненту с ASP-страницы экземпляр этого компонента (и любого другого внутри приложения COM+) создается внутри того же процесса, что и ASP-страница — если только поточная модель компонента совместима. Поскольку приложения COM+ допускают апартаментно-поточную, произвольно-поточную и нейтрально-поточную модели, экземпляр компонента приложения COM+ должен создаваться внутри процесса ASP-страницы, а все вызовы между сценарием страницы и компонентом должны выполняться в том же потоке.

Службы COM+

Компонент, с помощью диспетчера служб COM+ (COM+ Services Manager) установленный как часть приложения COM+, называется сконфигурированным компонентом (configured component). Такой компонент может воспользоваться преимуществами служб COM+, например, поддержкой транзакций и активацией по требованию. Компонент, не установленный как часть приложения COM+ и зарегистрированный с помощью инструментов разработки (например, VB) или утилиты regsvr32.exe, называется несконфигурированным компонентом (unconfigured component). Этот тип компонента использовать в ASP-приложениях можно, но реализовать интерфейс IObjectControl, воспользоваться преимуществами активации по требованию или применить объект ObjectContext для поддержки транзакций нельзя. Можно, однако, как и прежде, обратиться с помощью объекта ObjectContext к встроенным объектам ASP.

Одним из основных доводов в пользу добавления компонента в приложение COM+ является желание применить компонент в транзакциях. Это момент обсуждается в следующем разделе.

Поддержка транзакций

Одна из проблем при работе с компонентами, построенными на основе технологий COM/DCOM, состоит в том, что связь компонентов, особенно удаленная связь, весьма непроста. Выяснение того, успешно ли завершена обработка компонента, что делать дальше и как восстановить задачу, если один из компонентов не смог ее выполнить, а остальные — смогли, может превратить распределенную систему в плохо реализуемую и трудно управляемую.

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

Кроме того, MTS предоставляет менеджеров (managers) и диспетчеров (dispensers) ресурсов, которые управляют данными хранилищ, например, данными баз данных. По сути, любая система баз данных, поддерживающая транзакции OLE, скажем, SQL Server, может участвовать в транзакциях, управляемых MTS. Это означает, что если компонент, участвующий в транзакции, выполняется с ошибкой, то можно отозвать (вернуть к прежнему состоянию) не только его действия и действия других компонентов, но и любое действие, произведенное базой данных.

Все возможности MTS по работе с транзакциями реализованы в службах COM+ и доступны для сконфигурированных компонентов. Отличие состоит в том, что в COM+ (и Windows 2000) присутствует интерфейс IContextState, позволяющий отделить активацию компонента от управления транзакциями. Этот интерфейс способен сигнализировать, собирается ли компонент принять или прервать транзакцию, при этом компонент остается активированным, как было ранее показано в листинге 5.1.

Что такое транзакции?

Если вы имели опыт работы с коммерческими базами данных, например, с Oracle, Sybase и Microsoft SQL Server, то, возможно, знаете, что представляют собой транзакции. Транзакция (transaction) — это одна или несколько задач, некоторым образом логически сгруппированных, причем все задачи, объединенные в данную группу, либо все вместе успешно завершаются, либо все вместе не выполняются, если хотя бы одна из задач внутри транзакции не выполнена. Если транзакция не состоялась, никаких изменений данных, связанных с данной транзакцией, не делается. Если же выполнение транзакции происходит успешно, все изменения данных принимаются. В качестве примера транзакции с несколькими задачами можно привести перевод денег со сберегательного на расчетный счет. Хотя это и похоже на одну транзакцию, в действительности, происходят сразу две транзакции. Первая транзакция состоит в снятии ваших денег со сберегательного счета (то есть они дебетуются на счет), вторая транзакция заключается в переведении этих денег на расчетный счет (то есть они кредитуются на расчетный счет) . Если операция снятия денег со сберегательного счета прошла успешно, а операция по переводу денег на расчетный счет не была выполнена, вы, весьма вероятно, захотите, чтобы целиком вся транзакция была отозвана и начата заново. Транзакции очень существенны для систем, обновляющих несколько структур данных, например, баз данных. Такие обновления, даже основанные на одной операции, должны быть успешно завершены сразу для всех структур данных, именно для того, чтобы обеспечить успешное завершение одной этой операции.

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

Участие компонентов в транзакциях

Компонент может воспользоваться возможностями транзакций COM+, если он удовлетворяет следующим условиям. Во-первых, компонент должен быть внутрипроцессным сервером (то есть DLL). Во-вторых, он не должен быть свободно-поточным. Далее, если компонент создан в Visual С++, он должен реализовать фабрику классов (class factory) и использовать стандартную маршализацию. Кроме того, для компонента нужно будет создать библиотеку типов.

Если компонент удовлетворяет минимальным требованиям, чтобы получить поддержку транзакций, он должен быть зарегистрирован в COM+. В процессе регистрации тип транзакции, в которой участвует компонент, устанавливается в качестве свойства компонента. Например, на рис. 3 показано окно свойств компонента, для которого требуется транзакция, время ожидания завершения которой определено в 10 секунд.

Чтобы начать транзакцию на ASP-странице, поместите первой строкой страницы следующую директиву:

Для работы с транзакциями компонент должен ссылаться на экземпляр объекта ObjectContext (или интерфейса IObjectContext) или экземпляр интерфейса IContextState. Пометить компонент как готовый к принятию транзакции можно с помощью метода SetComplete объекта ObjectContext или метода SetMyTransactionVote интерфейса IContextState:

Пометить транзакцию для отзыва можно с помощью тех же интерфейсов:

Транзакции COM+ в действии показаны в примерах главы 9, посвященной созданию ASP-компонентов промежуточного слоя с помощью ADO. В этих примерах транзакции выполняются для обновления баз данных — и это их традиционное применение. Транзакции с базами данных можно выполнять непосредственно (не прибегая к транзакциям COM+) с помощью объекта ADO Connection. Тем не менее, примеры этой главы продемонстрируют, что гораздо удобней наладить взаимодействие компонентов и баз данных посредством транзакций COM+.

Транзакции COM+ можно также использовать для управления взаимодействием с другими ресурсами, например, с сообщениями в очереди сообщений. В главе 13, посвященной работе с компонентами MSMQ, транзакции управляют непрерывным удалением сообщений из очереди по мере получения к ним доступа.

Помимо поддержки транзакций и активации по требованию, службы COM+ могут также обеспечивать резервирование (pooling) компонентов.

Резервирование компонентов

Ранее уже отмечалось, что у интерфейса IObjectControl есть три метода: Activate, Deactivate и CanBePooled. У вас уже была возможность поработать с методами Activate и Deactivate, но для резервирования компонентов важен именно метод CanBePooled.

В случае резервирования объектов при пуске приложения COM+ создается минимальный резерв, или пул (pool), компонентов, и все запросы компонента обслуживаются из этого пула посредством менеджера пула (pool manager). Если менеджер получает запрос большего, чем имеется в пуле, числа экземпляров компонента, он создает другой экземпляр компонента, добавляя его в пул — до достижения максимального размера пула. Если же максимальный размер пула достигнут, запрос ставится в очередь до тех пор, пока компонент не станет доступным.

Компоненты, объединяемые в пул, должны соответствовать определенному набору условий. Во-первых, компонент не должен быть отдельно-поточным. Далее, компонент должен поддерживать агрегирование (aggregation), однако при этом свободно-поточный составитель (Free-Threaded Marshaler, FTM) использоваться не может.

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

Если компонент обращается к ресурсам, он должен реализовать три метода интерфейса IObjectControl — Activate, Deactivate и CanBePooled. Обратиться к ресурсу можно с помощью метода Activate (когда компонент создается на клиентской ASP-странице). Этот ресурс может быть высвобожден при высвобождении компонента клиентом (с помощью метода Deactivate). Кроме того, компонент обязан проверить, находятся ли его ресурсы в состоянии, когда их можно резервировать при деактивации компонента. Если резервирование возможно, метод компонента CanBePooled должен возвратить значение True, в противном случае, компонент должен возвратить значение False, чтобы предотвратить возврат компонента в пул.

Наконец, состояние компонента не должно зависеть от сеанса.

Создать резервируемый компонент можно с помощью Visual C++ (или любого другого языка, поддерживающего свободно-поточную или произвольно-поточную модели). Для демонстрации резервирования объектов создайте с помощью мастера ATL COM AppWizard новый проект Visual С++ и назовите его asp0502. Оставьте установленные по умолчанию параметры для MTS, MFC, заместителя (proxy) и исполнителя (stub).

После генерации файлов проекта добавьте новый компонент с помощью мастера ATL Object Wizard. (Подробно работа с этим мастером рассмотрена в главе 14.) Выберите тип Simple Object (Простой объект). Назовите компонент pooledComponent, на вкладке Attributes (Атрибуты) выберите произвольно-поточную модель и поддержку агрегирования (но не поддержку FTM).

Для поддержки интерфейса IObjectControl добавьте в определения класса в файле pooledComponent.h следующую строку:

Добавьте в данные COM ссылку на карту COM (COM map):

При работе с компонентом вам придется обращаться к интерфейсу IObjectContext и встроенному объекту ASP Response, поэтому добавьте в заголовочные файлы библиотеки типов службы COM+ и ASP следующее:

Следует также добавить прототипы метода интерфейса IObjectControl и ссылку на два закрытых (private) члена данных типа интерфейсов IObjectContext и IResponse (встроенного объекта ASP Response). Полный программный код заголовочного файла для резервируемого компонента показан в листинге 5.3.

Листинг 3. Заголовочный файл резервируемого компонента

// pooledComponent.h : объявление CpooledComponent

#ifndef __POOLEDCOMPONENT_H_
#define __POOLEDCOMPONENT_H_

#include «resource.h» // основные символы
#include
#include

/////////////////////////////////////////////////////////////////
// CpooledComponent
class ATL_NO_VTABLE CpooledComponent :
public CComObjectRootEx ,
public CComCoClass ,
public IObjectControl,
public IDispatchImpl
<
public:
CpooledComponent()
<
>

BEGIN_COM_MAP(CpooledComponent)
COM_INTERFACE_ENTRY(IpooledComponent)
COM_INTERFACE_ENTRY(IObjectControl)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()

// IpooledComponent
public:
STDMETHOD(Activate)();
STDMETHOD_(BOOL, CanBePooled)();
STDMETHOD_(void, Deactivate)();

private: CComPtr m_spObjectContext;
CComPtr m_piResponse;
>;

Далее, с помощью вкладки Link (Связь) диалогового окна Project Settings (Настройки проекта) добавьте в список связанных библиотек проекта библиотеку служб COM+ (comsvcs.lib).

Вам придется реализовать три метода интерфейса IObjectControl. В CPP-файле компонента добавьте код, показанный в листинге 5.4. В этом коде экземпляры IObjectContext и IResponse создаются в методе Activate и высвобождаются в методе Deactivate. Кроме того, метод CanBePooled возвращает значение True и помечает, что компонент можно резервировать (помещать в пул).

Листинг 4. Реализация компонентом методов интерфейса IObjectControl

HRESULT CpooledComponent::Activate()
<
HRESULT hr;
CComBSTR bstrProp;
CComVariant vt;
CComPtr pProps; //Свойства контекста

// получение ObjectContext
hr = CoGetObjectContext(IID_IObjectContext,
(void **)&m_spObjectContext);

if (FAILED(hr)) return hr;

// получение ContextProperties
hr = m_spObjectContext
->QueryInterface( IID_IGetContextProperties,
(void**)&pProps );
if (FAILED(hr)) return hr;

// получение свойства Response
bstrProp = «Response»;
hr = pProps->GetProperty( bstrProp, &vt ) ;
if (FAILED(hr)) return hr;

p > hr = piDispatch->QueryInterface( IID_IResponse,
(void**)&m_piResponse );
return hr;
>

void CpooledComponent::Deactivate()
<
m_piResponse.Release();
m_spObjectContext.Release();
>

BOOL CpooledComponent::CanBePooled()
<
return TRUE;
>

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

С помощью вкладки ClassView (Просмотр классов) добавьте новому компоненту не принимающий никаких параметров метод testPooledComponent. Этот метод прост: он выдает с помощью объекта Response сообщение для web-страницы. Добавьте компоненту программный код метода, показанный в листинге 5.5.

Листинг 5. Единственный метод резервированного компонента

STDMETHODIMP CpooledComponent::testPooledComponent()
<
// печать сообщения
CComVariant vt(«Привет от резервированного компонента»); m_piResponse->Write(vt);

Чтобы воспользоваться резервированием компонентов, компонент нужно добавить в приложение COM+. Создайте новое приложение — с помощью консоли управления службами компонентов (Component Services Management Console) — или воспользуйтесь существующим приложением COM+ и добавьте компонент в приложение.

Добавив компонент в приложение COM+, откройте с помощью контекстного меню диалоговое окно Properties (Свойства) и перейдите на вкладку Activation (Активация). Установите флажок объединения компонентов, задайте минимальный размер пула 10, максимальный — 20.

При первом запуске приложение COM+ создает пул из 10 уже созданных компонентов. При обращении с ASP-страниц к этим компонентам они извлекаются из этого пула до тех пор, пока все не будут активированы. После этого все новые вызовы компонентов будут добавлять экземпляры этих компонентов в пул, пока не будет достигнут максимальный размер пула в 20 экземпляров.

Протестируйте компонент с помощью следующей тестовой ASP-страницы (asp0502.asp):

На этой странице создаются 20 экземпляров компонента и вызывается метод каждого из компонентов. Результатом обращения к этой ASP-странице будет список сообщений со строкой «Привет от резервированного компонента». Первые 10 экземпляров были созданы при запуске приложения COM+, а последние 10 — при обращении к ASP-странице.

Измените теперь число экземпляров на 21 и обратитесь к ASP-странице. Похоже, она виснет. Это происходит потому, что менеджер пула выдал все компоненты из доступного пула, вследствие чего достигнут максимальный размер пула. Запрос 21-го компонента ставится в очередь до тех пор, пока какой-нибудь компонент не освободится. Но поскольку до завершения страницы все компоненты остаются недоступными, а запрос компонента происходит на той же самой странице, экземпляр 21-го компонента не может быть создан, и страница зависает. Фактически страница будут продолжать висеть до истечения времени ожидания запроса компонента. После этого страница выведет следующее сообщение об ошибке («активация COM+ не удалась, поскольку она не может быть завершена в течение заданного времени»):

COM+ activation failed because the activation could not be
completed in the specified amount of time.

Как было показано, резервирование объектов может служить весьма мощным ускорителем производительности, но оно же может и ограничить масштабируемость (scalability) или истощить ресурсы (поскольку резервируемые компоненты удерживаются в памяти). Пользуйтесь этой службой COM+ с осторожностью.

Internet Information Services: Масштабирование приложений ASP.NET: извлеченные уроки

Посетителей: 3382 | Просмотров: 5116 (сегодня 0) Шрифт:

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

Простая истина состоит в том, что ни одно приложение не масштабируется эффективно с первого раза – сделать все правильно с ходу невозможно. Чтобы успешно масштабировать приложение, необходимо понимать, как оно было построено, а также как работает его среда эксплуатации. Другими словами, необходима информация как от разработчиков, так и от специалистов по сетям. Без этих общих знаний успех невозможен.

Основы масштабирования

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

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

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

Сочетание специализации и распределения повышает эффективность – распределять можно только элементы приложения, нуждающиеся в дополнительной производительности. Например, если созданы специальные серверы изображений, но предоставление изображений все еще неадекватно, можно добавить серверы лишь для изображений, а не для всего приложения. Важно помнить про эти стратегии, когда углубляешься в улучшение производительности и масштабируемости своего приложения ASP.NET.

Встреча разумов

В жизненном цикле каждого приложения ASP.NET есть момент, когда разработчики, и специалисты по сети/ИТ, вероятно, встретятся. Если повезет, это произойдет до развертывания приложения, но порой это происходит только после возникновения кризиса – например, когда приложение отлично работает в тестовой среде, затем поставляется пользователям и еле ползет у них. (В таких случаях и вызывают консультантов вроде меня.)

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

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

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

Что специалистам по сетям нужно узнать от разработчиков

Каждое приложение ASP.NET имеет свои тонкости, существуют ключевые элементы, применимые во всех случаях. Одним из них является файл web.config (см. рис. 1). Web.config – это точка пересечения между разработкой и работой с сетью. Порой он настраивается разработчиками, порой специалистами по сетям. Так или иначе, содержание web.config накладывает ограничения на состав оборудования и настройку сети и прямо влияет на работу приложения. Подробное изучение всех мелких аспектов файла web.config может легко занять целую книгу; здесь же следует просто понять, что обеим группам необходимо изучить файл web.config и согласиться насчет того, что значит представляемая им настройка, а также того, какое влияние различные параметры будут иметь на приложение и на среду.

Рис. 1 Базовый файл web.config, показывающий некоторые параметры приложения и индивидуализированную настройку ошибок

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

Наконец, стоит обратить внимание, что с точки зрения масштабирования абсолютным значением ключа в файле web.config является тег , определяющий, где будут храниться данные сеанса для приложения. По умолчанию, данные сеанса хранятся «InProc», или в пространстве процессов приложения ASP.NET. Если данные сеанса настраиваются с учетом этого, то вся балансировка нагрузок должна быть «прилипчивой» – определенный пользователь всегда должен возвращаться к тому же серверу, где находятся данные сеанса. Это предмет для большого разговора между разработчиками и сетевиками, поскольку он прямо влияет на способы масштабирования и отказоустойчивости. Ранее обсуждение этого может сэкономить массу нервов, ушедших бы на устранение неполадок приложения.

После того, как разговор доходит до состояния сеанса, оттуда легко перейти к требованиям балансировки нагрузки приложения в целом. Некоторым средам необходимо специальное оборудование для балансировки нагрузки с конкретными функциями – но если приложение не поддерживает эти функции, они немногого стоят. Я сталкивался с ситуациями, когда аппаратная балансировка нагрузки использовалась с приложением ASP.NET, хранившим данные сеанса в процессе. В результате порой безо всякого объяснения терялись сеансы. Это выглядело как ошибка в приложении, но на деле было следствием неправильной настойки.

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

К тому времени, как приложение ASP.NET готово к развертыванию (или находится в процессе первоначального развертывания), разработчики будут иметь хорошее представление о том, какие области приложения работают быстро, а какие медленно. Что важнее всего, они будут чувствовать, где в системе находятся «узкие места» и потенциальные опасные точки. Если группа работы с сетью/эксплуатации знает об этих узких местах, она может подготовиться к проблемам заранее и, возможно, даже избежать их.

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

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

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

Ранняя беседа об элементах рабочей нагрузки такого рода в приложении может спасти от многих неприятностей впоследствии.

Что разработчикам по сетям нужно узнать от специалистов по сетям

Я люблю начинать часть встречи, где народ, работающий с сетью, объясняет свой мирок разработчикам, с представления схемы сети. Слишком часто разработчики видят сеть, как показано на рис. 2 – то есть, не как сеть, а просто как веб-серверы, обозреватели и Интернет.

Рис. 2. Простое представление сети в глазах разработчика

Реальность, само собой, куда сложнее. Схема, подобная рис. 3, ближе к истине, хоть и является упрощенной. При взгляде на рис. 3 немедленно возникают дополнительные вопросы, вроде: «Как пользователи виртуальной частной сети (Virtual Private Network – VPN) работают с этим приложением» или: «В чем разница проверки подлинности для внутреннего пользователя и общего пользователя» и так далее.

Рис. 3. Реальная картина сети, которую нужно понять разработчикам

Очевидно, что простого предоставления схемы сети недостаточно. Также важно объяснить сеть во всех подробностях, поскольку по простому взгляду на схему нельзя сказать, какие элементы повлияют на приложение. Необходимо рассказать о реальном процессе подключения общего пользователя, пользователя VPN и внутреннего пользователя. А рассказ о различных существующих, особенно в более сложных сетевых архитектурах в стиле DMZ, правилах брандмауэра естественным образом высветит потенциальные проблемы приложения.

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

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

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

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

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

Возвращаясь к масштабированию

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

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

Масштабирование приложения ASP.NET влияет как на персонал, занимающийся разработкой, так и работающий с сетью – так что имеет смысл задействовать в принятии решений обе группы. Часто сотрудничество может дать оригинальные решения, которые не обнаружились бы при работе по отдельности. Например, люди, работающие с сетью, могут знать о существующих аппаратных решениях внутри компании, которые могут помочь разработчикам обеспечить выполнение требований к производительности и масштабированию. Обсуждение различных деталей приложения и среды откроет эти возможности.

Совместная борьба с огнем

Материалы по масштабированию приложений ASP.NET

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

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

Первый вопрос по борьбе с кризисом такой: «Как мы обнаруживаем, что веб-узел задыхается под нагрузкой?» Слишком часто ответ бывает: «Мы получаем звонок от руководителя технологического отдела». Когда первым признаком проблем с веб-узлом является звонок от кого-то извне, это проблема. Приличное измерение должно сообщить о проблеме прежде, чем зазвонит телефон. Оно не остановит сам звонок, но, по крайней мере, даст время подготовиться к ответу. Ответы типа «В самом деле?» не улучшают карьерных перспектив.

Следующий вопрос – кому звонить первому? Кто отвечает за событие? Часто человек, работающий с сетью, получает первое предупреждение, а он может быть относительно неопытен, так что необходим четкий план решения. Кому звонить дальше? Задача состоит в выполнении ранней, быстрой диагностики, чтобы установить тип возникшей проблемы. Если это сбой в работе сети, дело одно. Но если это проблема масштабирования, то совсем другое. В случае проблем масштабирования рекомендуется раннее подключение кого-нибудь из группы разработки.

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

Часто если единственным решением является написание кода, событие закончится, прежде чем это можно будет сделать. Само собой, событие следует отметить, чтобы уточнить приоритеты разработки на будущее, но вряд ли разумно пытаться написать кучу кода и воткнуть его в рабочую среду без тщательного тестирования. Правило №1 любого пожарного – не раздувайте огонь.

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

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

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

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

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

Принципы работы и структура Web-приложений на основе ASP.NET

На самом деле при разработке Web-приложений на основе ASP.NET возможны два варианта организации Web-форм.

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

Во втором случае каждая Web-страница разделяется на две части: Web-форму и файл, содержащий программный код. При этом форма, как и в первом случае, сохраняется в файле с расширением .aspx , а программный код — в файле с расширением .cs . Такая модель обеспечивает лучшую организацию элементов Web-приложения за счет отделения пользовательского интерфейса от программной логики.

В примере, рассмотренном ранее, Web-страница разделена на две части, при этом форма и программный код хранятся в разных файлах.

В следующем примере, изображенном на рис. 1.7, показана аналогичная предыдущей Web-страница, в которой форма и программный код объединены в одном файле.

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

Как видно из рис. 1.8, при обращении клиента к Web-приложению последнее запускается на сервере IIS. Запущенное приложение формирует отклик. Для этого на сервере создается экземпляр запрошенной Web-формы, она генерирует HTML-текст отклика, который и передается браузеру клиента. Сразу после этого экземпляр Web-формы уничтожается. Пользователь, получив HTML-страницу, сгенерированную приложением, имеет возможность заполнять различные поля формы (тестовые поля, переключатели и т. п.). После заполнения всех необходимых полей формы пользователь инициирует отправку данных, введенных им в страницу, обратно на сервер. Это происходит за счет использования технологии обратной отсылки, которая вызывается при выполнении определенных действий (например, нажатия на кнопку). Получив данные от пользователя, сервер создает новый экземпляр Web-формы, заполняет его полученными данными и обрабатывает все необходимые события. По окончании обработки сервер формирует HTML-код ответа и отправляет его клиенту, а затем уничтожает экземпляр Web-формы. Более подробно описанный сценарий изображен на рис. 1.9 и 1.10.

В момент окончания работы с Web-приложением пользователь либо закрывает браузер, либо переходит на другую интернет-страницу. В этот момент завершается сеанс работы пользователя с данным приложением, однако само приложение может быть завершено сервером не сразу после окончания последнего сеанса работы пользователя. Это связано с управлением распределением памяти платформой .NET Framework, которая основана на периодической проверке ссылок объектов. Если в результате такой проверки обнаружится, что объект больше не используется, сервер уничтожает его, освобождая таким образом занимаемую им память. Поэтому нельзя точно сказать, когда именно наступит событие Application_End для данного Web-приложения.

Полезные советы по оптимизации ASP-приложений

Введение

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

Публикуемый ниже материал представляет собой первый совет из целой серии советов по оптимизации приложений, использующих технологии ASP и Visual Basic Scripting Edition (VBScript). Большинство из них были многократно обсуждены и c успехом проверены на веб-сайте Microsoft Corporation и других ASP-сайтах. Авторы материала подразумевают, что вы уже знакомы с основами разработки ASP-приложений, включая VBScript и/или JScript, ASP-сессиями и др. важными объектами (Request, Response и Server).

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

Типичная ASP-страница получает данные из базы данных и затем выводит их в формате HTML. Независимо от скорости вашей базы данных, получение данных из памяти сервера намного быстрее, чем обработка sql-запроса к конечной базе данных. Получение данных, сохраненных на локальном жестком диске, также обычно быстрее, чем получение информации из БД. Поэтому одним из основных путей увеличения скорости работы вашей ASP-страницы является кэширование часто используемой информации в памяти или на жестком диске.

Кэширование данных — это классический компромисс «место или время». Если вы избрали для кэширования правильный материал, вы можете видеть внушительное повышение производительности вашего приложения. Чтобы кэширование было эффективным нужно использовать для временного хранения только те данные, которые многократно используются для вывода и каждый раз трудоемки для повторных вычислений. Кэш, полный устаревшей информации, будет пустой тратой памяти сервера.

Данные, которые не изменяются часто, являются хорошим кандидатом для кэширования, потому что вам не надо будет волноваться относительно их синхронизации через какое-то время с конечной базой данных. Выпадающие списки (сombo-box), таблицы ссылок, пункты меню, и переменные конфигурации сайта (включая имена DSN, адреса IP и URL) — первые кандидаты для хранения в кэше. Заметьте, что вы можете кэшировать представление данных много быстрее, нежели данные сами себя. Если ASP-страница изменяется не так часто и ее временный кэш будет весьма внушительным (например, полный каталог изделий фирмы), попробуйте использовать сгенерированные HTML-страницы, чем каждый раз загружать сервер генерацией ASP-страниц.

Кэшируйте часто используемые данные в объектах Application или Session

Объекты Application и Session служат для хранения данных в памяти, значения которых могут быть доступны между несколькими HTTP-запросами (в отличие от обычных переменных, чьи значения доступны только в теле одной ASP-страницы). Данные объекта Session доступны только одному пользователю (в течении его сессии), в то время как данные Application доступны всем пользователям веб-сайта. Поэтому часто перед разработчиком возникает вопрос: в каком из объектов сохранять часто используемые данные. Обычно, для инициализации переменных этих объектов используются процедуры файла Global.asa — Application_OnStart() или Session_OnStart() соответственно. Если в вашем Global.asa еще нет этих процедур, то вы можете добавить их сами или инициализировать переменные, когда это будет необходимо. Примером может быть следующая процедура, использующая Application для хранения значений многократно использующейся переменной EmploymentStatusList. Процедура проверяет существование данных в EmploymentStatusList и при необходимости расчитывает их заново:

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

‘Сохранить значение recordset в виде массива

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

‘Сохранить значение recordset в виде HTML-списка

Кэшируйте данные на диске веб-сервера

Иногда в памяти вашего веб-сервера может быть слишком большое количество данных. «Слишком много», конечно, является спорным вопросом — это зависит от того, сколько памяти вы хотите использовать, а также число элементов для кэширования и частота, с которой эти элементы будут запрашиваться. В любом случае, если вы имеете слишком большое количество данных для кэширования в памяти, подумайте о переносе кэша в текстовый или XML-файл на жесткий диск веб-сервера. Вы можете одновременно комбинировать кэширование на диске и в памяти, чтобы сформировать оптимальную стратегию для вашего сайта.

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

ASP и COM обеспечивают несколько инструментальных средств для создания схем кэширования на диске. Функции набора записей ADO Save() и Open() сохраняют и загружают recordset c диска. Используя эти методы вы можете переписать код из прошлого совета, заменяя запись в объект Application на метод Save() для записи в файл.

Есть несколько других компонентов, которые работают с файлами:

* Scripting.FileSystemObject позволяет создавать, читать и записывать файл.
* MSXML, MicrosoftR XML parser поддерживает сохранение и загрузку XML-документов.
* Объект LookupTable (например, используемый на MSN.com) — лучший выбор для загрузки простых списков с диска.

Наконец, рассмотрите вопрос принудительного кэширования информации на диске. Сгенерированный HTML-код может быть сохранен на диске как .htm или .asp файл; гиперссылки могут указывать прямо на этот файл. Вы можете автоматизировать процесс генерации HTML, используя коммерческие инструментальные средства типа XBuilder или средства публикации в Интернет, входящие в MicrosoftR SQL ServerT. Кроме того, при помощи директивы #include можно включать отдельные HTML-части в файл ASP или читать HTML-файл с диска используя FileSystemObject. Например, на начальной странице vbCode (http://vbcity.com/vbcode/ru/home.asp) приводятся 10 последних тем обсуждения двух дискуссионных форумов. Отобразить эти списки можно при помощи создания двух наборов записей ADO при каждом обращении к данной странице или, следуя данному совету, сохранить их однажды в виде HTML-файла list.inc, а затем включать в home.asp:

Второй путь работает значительно быстрее.

Избегайте кэшировать медленные компоненты в объектах Application или Session

Несмотря на то, что кэшированиe данных в объектах Application или Session может быть хорошей идеей, кэширование COM-объектов может иметь серьезные ловушки. Занесение наиболее используемых COM-объектов в объекты Application или Session часто соблазняет, но, к сожалению, много COM-объектов, включая все, написанные в Visual Basic 6.0 или ранее, могут вызывать серьезные критические проблемы после сохранения в объектах Application или Session.

В частности, любой компонент, который выполняется медленно, вызовет критические проблемы когда кэшируется в объектах Session или Application. Быстрый (проворный non-agile) компонент — компонент, помеченный ThreadingModel=Both, который объединен Free-threaded marshaler (FTM), или — компонент, помеченный ThreadingModel=Neutral. (Neutral — новая модель в WindowsR 2000 and COM+). Следующие компоненты не проворны:

* Free-threaded components.
* Apartment-threaded components.
* Single-threaded component.
* Configured components (библиотека Microsoft Transaction Server (MTS)/COM+ и серверные приложения) не проворны пока они Neutral-threaded. Apartment-threaded components и другие не проворные компоненты хорошо работают в пределах страницы (т.е. создаются и разрушаются в пределах одной ASP-страницы).

В IIS 4.0 компонент, отмеченный ThreadingModel=Both выполняется быстро. В IIS 5.0 уже не так достаточно. Компонент не должен только быть отмечен как Both, он должен также объединен FTM.

IIS выполняет проверку компонентов, но если вы хотите ее отменить (т.е. хотите позволить непроворным компонентам быть сохраненными в объектах Application или Session), вы можете установить AspTrackThreadingModel в metabase в значение True. Но это (изменение AspTrackThreadingModel) не рекомендуется.

IIS 5.0 выдаст сообщение об ошибке, если Вы пытаетесь сохранить непроворный компонент, созданный с использованием Server.CreateObject, в объекте Application. Вы можете обойти это, используя в Global.asa, но это также не рекомендуется, поскольку это ведет к проблемам (очереди и сериализация), объясняемым ниже.

Что же все-таки неправильно если вы кэшируете непроворные компоненты? Непроворный компонент, кэшируемый в объекте Session блокирует Session от других рабочих потоков (thread) ASP. ASP обслуживает пул (контейнер) рабочих потоков, запрашиваемых другими сервисами. Обычно, новый запрос обрабатывается первым доступным потоком. Если Session блокирована, то запрос должен ждать поток, когда он станет доступным. Проведем аналогию, которая поможет понять эту ситуацию: вы идете в магазин, выбираете несколько булок, и платите за них в кассе #3. Всякий раз, после того как вы выбрали булки в том магазине, вы всегда оплачиваете их в кассе #3, даже в том случае, когда в других кассах короче очередь или даже вообще нет покупателей.

Сохранение непроворных компонентов в объект Application накладывает столь же негативный эффект на производительность. ASP создает специальный поток для выполнения меделенных компонентов в пределах Application. Это имеет два последствия: все запросы выстраиваются в очередь к этому потоку и все запросы сериализуются. Выстраивание в очередь означает, что параметры были сохранены в общедоступной области памяти; запросы переключаются к специальному потоку; метод компонента выполнен; результаты выстраиваются в общедоступную область. Сериализация (преобразование в последовательную форму) означает, что все методы выполняются в одно время. Для двух различных потоков ASP не возможно одновременное выполнение методов общедоступного компонента. Это уничтожает многопотоковость (параллелизм), особенно на мультипроцессорных системах. Хуже всего то, что все непроворные компоненты в пределах Application совместно используют один поток («Host STA»), так что негативные результаты сериализации налицо.

Смущены? Есть некоторые общие правила. Если Вы пишете объекты в Visual Basic (6.0 или ранее), не храните их в объектах Application или Session. Если вы не знаете потоковую модель объекта, не храните его в кэше. Вместо кэширования где-либо непроворных объектов, вы должны создать и удалить их на каждой странице. Объекты выполнятся непосредственно в рабочем потоке ASP и не будет никакой очереди или сериализации. Производимость будет адекватна, если COM-объекты запущены под IIS и если они не используют много времени, чтобы инициализироваться и уничтожаться. Заметьте, что однопотоковые (single-threaded) объекты не должны использоваться этот путь. Будьте внимательным — VB может создавать однопотоковые объекты! Если вы используете однопотоковые объекты, этот путь (типа таблицы Microsoft Excel) не рассчитывает на высокую производительность.

Наборы записей (recordset) ADO могут безопасно кэшироваться когда ADO отмечен как Free-threaded. Чтобы сделать ADO как Free-threaded используйте файл Makfre15.bat, который обычно зафиксирован в каталоге Program FilesCommon FilesSystemADO.

Предупреждение: ADO не должен быть Free-threaded, если вы используете Microsoft Access в качестве БД. Набор записей ADO должен быть также вообще отсоединен, если вы не можете управлять конфигурацией ADO на вашем веб-сайте.

Не кэшируйте соединение БД в объектах Application или Session

Кэширование соединений ADO — обычно плохая стратегия. Если один объект Connection сохранен в объекте Application и используется на всех страницах, то все страницы будут бороться за использование этого соединения. Если объект Connection сохранен в ASP-объекте Session, то соединение БД будет создано для каждого пользователя. Это создает излишнюю загрузку веб-сервера и БД.

Вместо кэширования соединений БД, создавайте и уничтожайте объекты ADO на каждой ASP странице, которая использует ADO. Это эффективно, потому что IIS имеет встроенное подключение БД. Более точно, IIS автоматически допускает объединение подключений OLEDB и ODBC. Это гарантирует, что создание и уничтожение связей на каждой странице будут эффективны.

Так как соединенные наборы хранят ссылки на подключение БД, это следует, что вы должны не кэшировать соединенные наборы в объектах Application или Session. Однако, вы можете безопасно кэшировать отсоединенные наборы, которые не держат ссылку на подключение. Чтобы отсоединить набор записей, сделайте следующие два шага:

Подробную информацию относительно подключений смотрите в справочниках по ADO и SQL Server.

Разумное использование объекта Session

Теперь, когда в предыдущих советах были раскрыты достоинства кэширования данных в объектах Applications и Sessions, мы собираемся предложить вам избегать использования объекта Session. Сессии имеют несколько ловушек когда используются на загруженных сайтах. Под «загруженными» имеются ввиду сайты с сотнями запрашиваемых страниц в секунду или тысячами пользователей одновременно. Этот совет также важен для сайтов, которые должны масштабироваться горизонтально — т.е. те сайты, которые используют несколько серверов для распределения нагрузки и обеспечения отказоустойчивости при сбоях. Для меньших сайтов, типа intranet-сайтов, преимущества применения Sessions все же перевешивают.

Обобщая, ASP автоматически создает Session для каждого пользователя, который обращается к веб-серверу. Каждая сессия занимает приблизительно 10 Кб памяти (сверх любых данных, сохраненных в Session) и немного замедляет выполнение всех запросов. Сессия остается действующей до окончания таймаута (timeout), обычно 20 мин.

Но самая большая проблема при использовании сессий — это не производительность, а расширяемость. Сессии не охватывают все задействованные веб-сервера; как только Session была создана на одном сервере ее данные остаются там. Это означает, что если вы используете сессии на мультисерверном веб-сайте, вы должны придумать стратегию для обработки запросов каждого пользователя, которые должны быть всегда направлены на сервер, на котором существует сессия этого пользователя. Это называется «застреванием» пользователя на сервере (или «липкой сессией»).

Объект Application также не охватывает все сервера: если вам нужно совместно использовать и обновлять данные Application через веб-сервера, вам нужно использовать конечную базу данных. Однако неизменяемые (read-only) данные Application все же полезны на мультисерверных сайтах.

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

Если же вы не используете Session, то убедитесь, что отключили их. Это можно сделать посредством Internet Services Manager (см. документацию по ISM). Но если вам все-таки необходимо использовать сессии, то есть несколько путей уменьшить их удары про производительности.

Вы можете переместить содержимое, которое не требует сессий (например, страницы help и т.д.) в отдельное ASP-приложение, у которого сессии выключены. Кроме того, на страницах, где объект Session не используется, применяйте следующую директиву, помещещаемую вверху страницы:

Одна из основных причин ее применения — то, что Session создает интересную проблему в случае использования фрэймов (frameset). ASP гарантирует, что в любое время будет выполняться только один запрос от Session. Это делается для того, чтобы при одновременном запросе одним пользователем нескольких страниц, только один ASP-запрос был обработан сессией, что помогает избежать проблем многопоточного доступа к объекту Session. К сожалению, в результате этого все страницы в frameset будут загружаться последовательно, а не одновременно, и пользователю придется продолжительное время ждать полной загрузки. Мораль этой истории: если вы не уверены, что с использованием фрэймов и Session ваше приложение правильно работает, то используйте:

Альтернативой использованию объекта Session являются многочисленные параметры управления Session. При передаче малых объемов данных (менее 4 Кб) обычно рекомендуется использовать Cookies, переменные QueryString и скрытые (hidden) переменные форм. При использовании большого количества передаваемых параметров (например, корзина произведенных заказов в он-лайн магазине) наиболее лучший выбор — конечная база данных.

Стратегии масштабирования для приложений ASP.NET

Как советников по производительности ASP.NET нас обычно привлекают к проекту, когда проблемы уже возникли. Во многих случаях, вызов приходит только тогда, когда приложение уже в производстве. То, что работало отлично для разработчиков, не работает для пользователей. Жалоба: веб-узел работает слишком медленно. Руководство хочет знать, в чем причина и почему ее не обнаружили при тестировании. Разработчики не могут воспроизвести проблему. По крайней мере, один человек утверждает, что ASP.NET не масштабируется. Звучит знакомо?

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

Уравнение производительности

В сентябре 2006 года Питер Севчик (Peter Sevcik) и Ребекка Ветцель (Rebecca Wetzel) из компании NetForecast опубликовали документ, именуемый «Field Guide to Application Delivery Systems» («Полевое руководство по системам доставки приложений»). Основное внимание в документе было уделено улучшению производительности приложений в глобальных сетях (wide area network — WAN), и в нем было приведено уравнение с рис. 1. Это уравнение рассматривает производительность глобальных сетей, но с несколькими мелкими изменениями его можно использовать и для измерения производительности веб-приложений. Измененное уравнение показано на рис. 2, а его элементы объяснены на рис. 3.

Рис. 1 The Original Performance Equation

Рис. 2 The Web Version of the Performance Equation

Рис. 3 Элементы уравнения производительности

Переменная Определение
R Время ответа. Общее время с запроса страницы пользователем (обычно переходом по ссылке и т.п.) до полной визуализации страницы на его компьютере. Обычно измеряется в секундах.
Объем полезных данных Общее число байтов, отправленных обозревателю, включая разметку и все ресурсы (такие как файлы CSS, JS и изображений).
Пропускная способность Скорость передачи данных обозревателю и от него. Может быть асимметрична и представлять несколько скоростей, если данная страница создается из нескольких источников. Обычно усредняется для создания единого выражения пропускной способности в байтах в секунду.
AppTurns Число файлов ресурсов, требуемых страницей. Они включают файлы CSS, JS, изображений и любые другие файлы, извлекаемые обозревателем в процессе визуализации страницы. Уравнение учитывает страницу HTML отдельно, добавляя время приема-передачи (round-trip time — RTT) перед выражением AppTurns.
RTT Время, необходимое для приема и передачи данных, вне зависимости от числа переданных байтов. Каждый запрос тратит минимум одно RTT для самой страницы. Обычно измеряется в миллисекундах.
Одновременные запросы Число одновременных запросов файлов ресурсов, которые выполнит обозреватель. По умолчанию Internet Explorer выполняет два одновременных запроса. Данный параметр может быть изменен, но это делается редко.
Cs Время вычислений на сервере. Время, уходящее у кода на запуск, извлечение данных из базы данных и составление ответа, отправляемого обозревателю. Измеряется в миллисекундах.
Cc Время вычислений на клиенте. Время, уходящее у обозревателя на визуализацию HTML на экране, исполнение JavaScript, применение правил CSS, итд.

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

Объем полезных данных можно измерить с помощью различных средств (отличным вариантом является websiteoptimization.com/services/analyze), точно так же, как и пропускную способность (см. speedtest.net) и время приема-передачи (используя программу Ping). Средства вроде websiteoptimization.com/services/analyze также сообщат размер HTML, CSS, JavaScript, изображений и прочих частей веб-страницы. Число одновременных запросов по сути являются постоянной (для Internet Explorer® по умолчанию используется 2).

В результате остаются только Cs и Cc (времена вычислений на сервере и клиенте), измерение которых требует некоторых дополнительных усилий от разработчика. Написание кода на странице ASP.NET, отмечающей точную секунду, когда начинается исполнение страницы, и вычитающей это время из текущего времени при завершении исполнения, является сравнительно простой задачей. Это же верно и для клиента — небольшой кусок кода на JavaScript может быть исполнен прямо наверху страницы HTML, чтобы отметить время и затем вычесть время на момент запуска события OnLoad при завершении страницы.

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

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

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

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

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

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

Оптимизация кода

При оптимизации серверного кода весь фокус состоит в использовании тестирования для проверки наличия реальных результатов. Для анализа приложения и поиска мест в приложении, вызывающих наибольшие затраты времени, следует использовать профилирование. Весь процесс должен быть основан на эксперименте: используйте средства чтобы найти код, который следует улучшить, улучшите код, проведите тестирование, чтобы увидеть, улучшилась ли производительность, повторяйте до получения нужных результатов. Для действительно крупных веб-узлов настройку производительности часто сравнивают с покраской моста «Золотые врата»: к тому времени, как докрасишь его до конца, в начале краска уже облезла, и пора браться за дело снова.

Меня всегда поражает число людей, считающих, что масштабирование начинается с распределения. «Нужно больше оборудования!» — кричат они. Не поймите меня неправильно: добавление оборудования, без сомнения, может помочь. Но без специализации и оптимизации отдача будет минимальной.

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

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

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

Чтобы применить распределение, необходимо добавить новые серверы, продублировать приложение на них и организовать балансировку нагрузки. Для балансировки нагрузки можно использовать службу балансировки сетевой нагрузки (Network Load Balancing — NLB), входящую во все версии Windows Server® 2003. NLB делает каждый сервер равноправным партнером в отношении балансировки нагрузки. Все они используют одинаковый алгоритм балансировки, и все они прослушивают весь трафик на общем виртуальном IP-адресе. Основываясь на алгоритме балансировки нагрузки, каждый сервер знает, какой сервер должен работать над каждым конкретным запросом. Каждый сервер в кластере оправляет периодический сигнал, давая остальным знать, что он работоспособен. При сбое сервера периодический сигнал для него останавливается, и остальные серверы компенсируют потерю выбывшего автоматически.
NLB хорошо работает при наличии большого числа пользователей, делающих довольно похожие запросы. Однако механизм компенсации работает хуже в ситуации, где некоторые запросы создают намного большую нагрузку, чем другие. К счастью, для такого типа ситуаций доступны решения балансировки нагрузки на основе оборудования.

Сходство

В конечном счете, сложность эффективного распределения состоит в ликвидации сходства. Например, при наличии только одного веб-сервера хранение на нем данных сеанса вполне понятно. Но где хранить сведения о сеансе при наличии более чем одного веб-сервера?

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

Но в долгосрочной перспективе сходство создает затруднения. Хранение данных сеанса в процессе может быть быстрым, но если рабочий процесс ASP.NET перезапускается, все эти сеансы погибают. А рабочие процессы перезапускаются по множеству причин. При высокой нагрузке IIS может перезапустить рабочий процесс ASP.NET, посчитав его зависшим. Более того, по умолчанию IIS 6.0 перезапускает рабочий процесс каждые 23 часа. Это можно скорректировать, но, так или иначе, пользователям угрожает потеря данных их сеанса, пока они в процессе. Пока веб-узел невелик, это не такая уж проблема, но по мере его роста и увеличения занятости растет и она. И это еще не все.

В случае балансировки нагрузки по IP-адресу один из серверов непременно столкнется с мега-прокси (вроде AOL) и будет неспособен обслужить всю эту нагрузку самостоятельно. Кроме того, перевод серверов на новые версии приложения становится более сложным — необходимо либо ждать часами, пока пользователи закончат операции на веб-узле, либо раздражать этих пользователей, прерывая их сеансы. Становится проблемой и надежность: с потерей сервера теряется масса сеансов.

Устранение сходства является ключевой задачей распределения. Это требует вывода данных о состоянии сеанса из процесса, что означает уменьшение производительности ради увеличения масштабируемости. При выводе сеанса из процесса данные сеанса сохраняются там, где к ним могут получить доступ все веб-серверы — либо в SQL Server®, либо на сервере состояния ASP.NET. Это настраивается в web.config.

Поддержка внепроцессного сеанса также требует определенных усилий по написанию кода. Все классы, которые будут храниться в объекте Session («Сеанс»), следует пометить атрибутом Serializable («Сериализуемый»). Это значит, что все данные в классе должны быть либо сериализуемыми, либо помеченными как NonSerialized («Не сериализуемые»), чтобы класс был проигнорирован. Если не разметить классы, то возникнут ошибки при переносе сеанса сериализатором из процесса в хранилище.

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

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

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

Сведение к минимуму объема полезных данных

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

Один из простейших способов уменьшить объем полезных данных — включить сжатие. В IIS 6.0 можно указать, следует ли сжимать статические файлы, динамически созданные ответы (страницы ASP.NET, например) или то и другое (см. рис. 4).

Рис. 4 Configuring Compression Server-Wide in IIS 6.0

IIS 6.0 сжимает статические файлы по требованию, сохраняя их в указанном кэше сжатых файлов. Для динамически созданных ответов копии не сохраняется, они сжимаются каждый раз. IIS 7.0 подходит к сжатию более разумно, сжимая только часто используемые файлы.

При сжатии тратится процессорное время, но на специализированном веб-сервере мощности ЦП обычно имеется в избытке. Тем не менее, IIS 7.0 дополнительно оптимизирован так, что процессы сжатия откладываются, когда процессор серьезно загружен. Существуют также специализированные устройства сжатия, независимые от самого веб-сервера.

Другая область с богатыми возможностями уменьшения объема данных — состояние представления (ViewState). В ходе разработки использование состояния представления может запросто выйти из-под контроля. Большинство веб-элементов управления используют состояние представления в какой-то мере, так что на страницах, где их много, состояние представления может разрастись до тысяч байтов. Чтобы уменьшить использование состояния представления, отключайте его на элементах управления, когда оно не нужно. В некоторых случаях разработчики даже устраняют элементы управления, чтобы уменьшить состояние представления. Но это не всегда обязательно. Большинство современных веб-элементов управления чувствительны к проблеме избыточного состояния представления и предоставляют детальный контроль над его размером. Существует также оборудование, способное удалять и заменять состояние представления, не изменяя код или то, как работает приложение.

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

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

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

Кэширование

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

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

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

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

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

На загруженном сервере ASP.NET память становится существенной проблемой по ряду причин. При каждом вычислении страницы ASP.NET используется некоторое количество памяти. И Microsoft® .NET Framework настроена на очень быстрое выделение памяти, но сравнительно медленное ее высвобождение через сбор мусора. Рассказа о сборе мусора и выделении памяти .NET хватит на отдельную статью (написанную уже не раз). Достаточно сказать, что на загруженном веб-сервере 2 ГБ пространства памяти, доступных приложению ASP.NET, пользуются большим спросом. В идеале большая часть этого использования памяти является временным, поскольку память выделяется переменным и структурам, используемым при вычислении веб-страницы.

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

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

Когда общий процент используемой памяти приближается к пределу памяти кэша ASP.NET по умолчанию (90%), вызывается событие сборки мусора. Событие сборки мусора проходит по пространству памяти, перемещая вниз задержавшиеся в ней объекты (вроде объектов кэша и объектов сеанса) и освобождая более не используемую память (которая была задействована для вычисления веб-страниц). Освобождение неиспользуемой памяти происходит быстро — в отличие от перемещения задержавшихся объектов. Так что чем их больше, тем сложнее сборщику мусора выполнить его работу. Этот тип проблемы можно опознать в perform.exe по большому числу коллекций gen-2.

И помните, что пока идет сборка мусора, этот сервер ASP.NET не может обслуживать страницы; все остальное ждет в очереди, ожидая завершении процесса сборки мусора. А IIS наблюдает за этим. Если покажется, что процесс занимает слишком долго и, возможно, завис, то рабочий поток будет перезапущен. И хотя это очень быстро высвободит массу памяти, выбросив все эти задержавшиеся в памяти объекты, некоторые клиенты явно будут недовольны.

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

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

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

Возможно проблема состоит в схеме истечения срока кэширования: истечение срока по времени неудовлетворительно. Можно кэшировать число в каталоге до момента, когда кто-нибудь купит штуковину, после чего завершить пребывания объекта в кэше. Это более логично, но что произойдет при наличии более чем одного сервера ASP.NET? В зависимости от сервера, в каталоге будет указываться разное число штуковин. Если учесть, что получение нового каталога (добавляющего к цифрам) даже не пройдет через веб-приложение, то получается целый новый способ сделать все неправильно.

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

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

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

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

А теперь пройдемся по этому случаю снова: приходит первый запрос, обнаруживает, что элемент кэша не заполнен, применяет блокировку к коду и выполняет запрос на заполнение объекта кэша. Второй запрос прибывает через секунду, пока первый еще работает, обнаруживает, что объект кэша не заполнен, но существует блокировка и блокируется. Как и следующие 28 запросов. Затем первый из них завершает свой процесс, снимает блокировку и продолжает. Что происходит с остальными 29 запросами? Они больше не блокированы, так что они также продолжают исполняться. Но они уже проверили объект кэша на заполненность (в момент, когда он не был заполнен). Так что они попытаются ухватить блокировку, одному это удастся, и он выполнит запрос снова.

Проблема ясна? Другие запросы, прибывающие после того, как первый запрос завершил заполнение объекта кэша, будут работать нормально, но запросы, прибывшие в ходе этого процесса, попадают в трудную ситуацию. Необходимо написать код для избежания этого. Если запрос сталкивается с блокировкой, то после ее отмены он должен проверить снова, не заполнен ли объект, как показано на Рис. 5. Скорее всего, теперь он заполнен, этим и было обусловлено само наличие блокировки. Хотя возможно и обратное из-за того, что какая-то другая часть кода вновь сделала объект кэша истекшим.

Рис. 5 Проверка, блокировка и повторная проверка объекта кэша

Написание хорошо работающего кода кэширования — трудная работа, но отдача может быть громадной. Однако кэширование повышает сложность, так что используйте его с умом. Убедитесь, что эта сложность даст реальные выгоды. Всегда тестируйте код кэширования для подобных сложных случаев. Что произойдет при нескольких одновременных запросах? Что произойдет при быстрых истечениях срока кэширования? Ответы на эти вопросы необходимо знать. Код кэширования должен решать, а не обострять проблемы масштабирования,.

Масштабирование баз данных

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

Однако, когда дело доходит до масштабирования баз данных, обычной практикой является наращивание — одна гигантская система, возможно две в кластере (хотя только одна реально несет на себе базу данных в каждый конкретный момент времени). Но рано или поздно каждое крупное веб-приложение доходит до стадии, когда одной базы данных недостаточно. Необходимо расширяться. Если возможно, достаточно применить те же стратегии масштабирования, что и к самому веб-приложению. Первым действием всегда является специализация — разбиение базы данных на логические разделы. Эти разделы могут быть основаны на разделении данных, возможно по регионам. В результате получится несколько баз данных, каждая из которых содержит часть изначальной базы данных. Например, один сервер будет содержать данные по восточному берегу США, а второй по западному берегу.

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

Рис. 6 Distributed Database Architecture

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

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

Бесконечная работа над масштабированием

Пока приложение продолжает расти, продолжит расти и работа по его масштабированию. Приемы ASP.NET, эффективно работающие с 10 000 одновременно подключенных пользователей, не так эффективны для 100 000, а для 1 миллиона пользователей правила меняются снова. Конечно, производительность может полностью зависеть от приложения, в некоторых из тех, что мы видели, проблемы с масштабированием начинались при менее чем тысяче пользователей!

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

ASP .NET — технология разработки Web-приложений от Microsoft

Технология Active Server Pages .NET (ASP .NET) — один из важнейших компонентов всей архитектуры Microsoft .NET. Обоснование этого утверждения вполне очевидно — ведь стратегической целью .NET объявлено создание инфраструктуры для разработки и функционирования распределенных приложений на базе Интернет-стандартов.

Говоря об Интернет-приложениях, мы традиционно подразумеваем в первую очередь Web-приложения, т. е. такие серверные программы, доступ к которым пользователи получают через Web-браузер. Именно для создания подобных Web-приложений предназначена технология ASP .NET. Однако полезно напомнить, что под определение «распределенные» (в классическом его понимании) гораздо больше подходят системы, реализованные на основе иных механизмов удаленного взаимодействия программных компонентов. Применительно к .NET — это технологии XML Web Services (на базе открытых стандартов) и .NET Remoting (внутренние протоколы Microsoft)*.

*О технологиях Web Services и .NET Remoting см. соответственно статьи в «BYTE/Россия» № 9’2001 и «Remoting.NET, или Удаленное взаимодействие объектов есть», «BYTE/Россия» № 4’2002.

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

В кулуарных разговорах мы довольно часто снисходительно говорим о казалось бы откровенных «ляпах» в тех или иных продуктах. Но что скрывается за этими «прорехами» — недальновидность поставщика, его неспособность к решению технических задач или тонкий стратегический расчет? Впрочем, какое дело нам, пользователям, до бизнес-проблем поставщика — мы ведь лишь выбираем наиболее подходящую технологию. Но все обстоит не так просто, хотя бы потому, что эту технологию приходится увязывать со многими другими вещами. И судьба поставщика нам не безразлична — если он обанкротится, то что мы будем делать с его прекрасной технологией?

Именно в контексте этого соображения мне хотелось бы еще раз обратить внимание на вопрос, который я в той или иной степени затрагиваю во всех своих публикациях по этой тематике: что же такое Microsoft .NET?

От ASP к ASP .NET

В конце 1997 г. Microsoft предложила технологию Active Server Pages (ASP) как средство динамического формирования HTLM-страниц. ASP изначально представляет собой часть сервера Microsoft Internet Information Server. ASP .NET (сначала она называлась ASP+) — это новая версия ASP.

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

Впрочем, механизм разделения HTML и программного кода был реализован и в старой версии ASP. Многие Web-разработчики заблуждаются, думая, что ASP связана исключительно с применением VBScript или JavaScript. На самом деле IIS задействует технологию Active Scripting, открытые интерфейсы которой позволяют разрабатывать и подключать произвольные языки сценариев. Именно эта возможность используется в Web-компоненте фирмы «1С», предусматривающем создание ASP-приложений с применением встроенного языка «1С:Предприятие 7.7» (см. «Разработка Web-приложений для «1С:Предприятие», «BYTE/Россия» № 4’2001, с. 48).

Более того, вариант создания Web-приложений, реализованный в Visual Basic 6.0 (см. статью «Visual Basic 6.0 упрощает разработку для Web» по адресу http://www.microsoft.com/rus/msdn/library/kolesov), предполагал как раз отделение программного кода от пользовательского интерфейса (HTML-кода) и оформление его в виде ActiveX DLL. Другое дело, что визуальные средства разработки Web-приложений в VB 6.0, хотя и знаменовали прогресс по сравнению с VB 5.0, но были откровенно слабее того, что предлагается для создания обычных Windows-приложений. Да и сама логика Web-разработки была отнюдь не простой.

Здесь мы подходим к формулировке второй задачи, которая стояла перед создателями Visual Studio .NET: сделать так, чтобы разработка Web-приложений была не сложнее программирования традиционных Windows-приложений и чтобы можно было максимально перенести опыт Windows-разработки в сферу Интернета.

Отметим сразу — обе эти задачи (отделение HTML от исполняемого кода и объединение логики разработки для Web и для Windows) в целом Microsoft решила. Но при этом подчеркнем: вся технология ASP .NET функционирует только в среде .NET.

Простейшее Web-приложение

Давайте посмотрим, как выглядит общая логика разработки простейшего приложения ASP .NET. Запустим Visual Studio .NET и создадим новый проект типа ASP .NET с использованием языка Visual Basic (рис. 1). Откроем окно с панелью инструментов Toolbox, выберем на ней вкладку Web Forms и с ее помощью разместим на форме проекта три элемента управления — Label1, TextBox1 и Button1.

Рис. 1. Выбор проекта Web Application в Visual Studio .NET.

Мы хотим, чтобы при нажатии командной кнопки Button1содержимое текстового поля TextBox1 заносилось в метку Label1. Для этого дважды щелкнем по изображению кнопки и в раскрывшемся окне кода введем программу обработки для события Button1_Click:

Запустим созданный проект на выполнение и убедимся, что он работает, как и было задумано (рис. 2). Как мы видим, разработка Web-приложения практически ничем (по крайнем мере, пока) не отличается от создания традиционной Windows-программы.

Рис. 2. Разработка проекта ASP .NET: на заднем плане — окно со средой разработки VS.NET, на переднем — окно Internet Explorer с созданным нами Web-приложением.

А теперь разберемся, из чего состоит наше простейшее приложение. В правом верхнем углу панели Solution Explorer (рис. 2) мы видим несколько компонентов, но сейчас нас интересует только модуль WebForm1.Aspx, который и является файлом ASP .NET, загружаемым в браузер. Просмотрим его содержимое, открыв вкладку HTML:

Обратите внимание, что модуль WebForm.aspx.vb (кстати, использование «точки» в составном имени файла представляется крайне неудачной идеей — возникает постоянная путаница с самим названием и типом файла) в явном виде никак не отображен в окне Solution Explorer, так как он должен быть однозначно привязан к основному ASPX-файлу.

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

Теперь поставим еще один небольшой эксперимент. Добавим в проект одну командную кнопку, но только не из вкладки Web Forms, а из HTML. В ASPX-файле она будет описана таким тегом:

Формирование обрабатывающего кода для кнопки выполняется аналогичным образом (но только сначала нужно правой кнопкой мыши вызвать контекстное меню для этого элемента и указать для него режим Run as Server Control). Однако между двумя вариантами кнопок есть одно принципиальное различие — в обычном HTML-редакторе, например, FrontPage, будут видны только стандартные элементы управления HTML (в нашем случае — одна командная кнопка).

Этот момент представляется очень важным, так как технология разработки Web-приложений, реализованная в VS.NET, принципиально отличается от схемы работы традиционных HTML-редакторов, которые сегодня (пока) не поддерживают работу с отдельными файлами программного кода. Перед искушенными Web-дизайнерами неминуемо возникнет дилемма: воспользоваться мощными средствами программирования VS.NET или богатыми средствами Web-дизайна профессиональных HTML-редакторов?

Какой из этих двух вариантов получит наибольшее распространение, мы увидим в недалеком будущем, но мой прогноз таков: учитывая упорство Microsoft в достижении своих целей, можно практически гарантировать, что независимым разработчикам HTML-редакторов неминуемо придется позаботиться об интеграции с технологией ASP .NET вообще и с Visual Studio .NET в частности.

Специальный инструмент разработки приложений ASP .NET

В июле 2002 г. Microsoft выпустила предварительную «технологическую» версию (Technology Preview) специализированного визуального инструмента для разработки ASP .NET — ASP .NET Web Matrix. Ее можно бесплатно загрузить с сайта http://www.asp.net (дистрибутив 1,2 Мбайт). Авторские права на продукт принадлежат Microsoft, но он был разработан не сотрудниками корпорации, а группой независимых специалистов, которая выполняет заказы ASP-подразделения Microsoft в свободное от основной работы время (среди авторов программы встречаются и русские имена).

Первая строка кода проекта была написана ровно за год до выпуска его «технологического» релиза, сейчас в нем около 150 тыс. строк. ASP .NET Web Matrix написан на C# и .NET Framework, пользовательский интерфейс реализован с помощью Windows Forms, доступ к данным — на базе ADO.NET. Некоторая часть ресурсов и служб пакета (в частности, справочная система) размещена на сервере http://www.asp.net, обращение к ним выполняется через механизм XML Web Services.

Конструктор страниц Web Matrix предоставляет интегрированные средства для создания и редактирования баз данных SQL и MSDE. Код ADO.NET для выполнения SQL-запросов и хранимых процедур генерируется автоматически; связывание данных страниц не требует написания кода. С помощью Web Matrix пользователь может встраивать в свои приложения поддержку XML Web Services, разрабатывать мобильные Web-приложения для таких устройств, как сотовые телефоны, пейджеры и PDA. Для разработки и тестирования приложений ASP .NET не требуется сервер IIS — Web Matrix включает облегченный варианта персонального Web-сервера, в котором многие функции (например, поддержка страниц ASP .NET иXML Web Services) реализованы в локальном режиме.

Пакет также обеспечивает поддержку рабочих пространств на основе FTP или обычной файловой системы, без серверных расширений FrontPage. Предусмотрен встроенный порт для общения с внешним миром, в том числе с различными форумами и группами новостей по тематике ASP .NET.

Будучи удобным специализированным инструментом, Web Matrix все же вряд ли сможет заменить Visual Studio .NET при создании профессиональных приложений. Прежде всего Web Matrix (по крайней мере в предварительном «технологическом» варианте) не поддерживает основную для ASP .NET идею разделения кодов. У него существенно слабее средства отладки, нет редактора с интеллектуальной подсказкой, не говоря уже о применении средств категории Enterprise. Продукт не будет поддерживаться службой Microsoft Product Support Services — вся поддержка будет выполняться онлайновым сообществом независимых разработчиков (http://www.asp.net).

Чтобы познакомиться с Web Matrix, создадим с его помощью простое приложение, аналогичное тому, что мы сделали в VS.NET.

Откройте Microsoft ASP .NET Web Matrix — появится диалоговое окно New File, в котором мы видим несколько различных начальных шаблонов проекта (рис. 3). Обратите внимание, что для каждой категории шаблонов, представленных в левом окне (Data Pages, Mobile Pages и пр.), имеется своя группа типов проектов. Выберите шаблон проекта General и ASP .NET Page, а в списке Language укажите Visual Basic, после чего нажмите OK.

Рис. 3. Web Matrix предлагает разные шаблоны для создания Web-приложений.

Со вкладки Web Controls панели инструментов Toolbox перетащите на создаваемую страницу элементы управления Label, TextBox и Button. Двойным щелчком на изображении кнопки перейдите к редактированию ее процедуры Button1_Click. Введите следующий код:

Запустите приложение на выполнение и убедитесь в его работоспособности. Теперь рассмотрим содержание созданного приложения. В среде разработки Web Matrix отсутствует панель Solution Explorer, из чего можно сделать предположение (совершенно справедливое), что весь проект состоит из одного ASPX-файла — в нем нет многочисленных дополнительных компонентов, которые мы видели в VS.NET. Нет здесь и отдельного VB-модуля с программным кодом.

Чтобы убедиться в этом, откроем вкладку All основного окна проекта и посмотрим полное содержание файла NewFile.aspx:

Иными словами, ASPX-файл состоит из двух частей — исполняемого (в данном случае VB) кода и HTML-кода (нет двух отдельных файлов, как это сделано в VS.NET). Для удобства работы с ними мы можем использовать вкладки HTML и Code окна проекта. Что интересно — мы можем загрузить в Web Matrix проект, созданный ранее в VS.NET, и запускать его на выполнение. Но редактирование VB-модуля при этом недоступно.

Впрочем, повторим, что пока мы имеем дело лишь с версией Technical Preview, да и вообще, вряд ли стоит всерьез сравнивать бесплатные продукты и коммерческие системы, являющиеся основой бизнес-стратегии огромной корпорации. Тем не менее Web Matrix вполне годится для обучения и реализации небольших проектов, к тому же в нем реализовано несколько очень интересных идей по организации среды разработки.

ASP .NET — что нас ждет впереди

Эта статья не может претендовать даже на введение в ASP .NET. Данной тематике посвящено не менее двух десятков книг (правда, пока по преимуществу выпущенных в США). Отметим только, что в ASP .NET существенно расширена функциональность ASP, улучшена ее способность создавать сложные масштабируемые Web-приложения (отметим, например, новые функции управления сеансами и администрирования, улучшенные средства безопасности).

Для более детального изучения этих вопросов можно рекомендовать англоязычные ресурсы на серверах http://msdn.microsoft.com и http://www.asp.net, в частности, статьи Cache and Carry with ASP .NET (вопросы кэширования для повышения производительности) и Migrating to ASP .NET. Key Considirations (переход от ASP к ASP .NET).

А закончить статью хочу таким размышлением. Многие профессиональные Web-разработчики пока весьма прохладно относятся к технологии ASP, считая ее излишне упрощенной и не очень эффективной (однако обратите внимание — для тиражируемых решений ее применяют довольно часто!). ASP .NET выглядит гораздо более привлекательно благодаря улучшенной функциональности и упрощению самой процедуры разработки. Но самое главное даже не в этом. Обратите внимание, что развитие технологии идет в типичном для Microsoft стиле: корпорация не пытается догонять конкурентов в вопросах, где позиции последних уже очень сильны (например, в Web-дизайне). Microsoft делает акцент на новшества, связанные с ее традиционными преимуществами. Причем реализуется это в виде в целом привлекательных решений, которые при этом не очень соответствуют общепринятым стандартам.

О разделении исполняемого кода и HTML уже говорилось выше. (код можно писать на многих языках программирования, например, Perl, но при условии, что они адаптированы для .NET). Другим принципиальным новшеством технологии ASP .NET стал новый тип компонентов — управляющие элементы Web. Очень важно, что их могут создавать независимые разработчики (причем даже не очень квалифицированные). Тут можно вспомнить, что одной из главных причин успеха VB в начале 90-х годов было создание огромного рынка дополнительных элементов VBX/OCX, которые существенно расширяли возможности самого VB.

Похоже, Microsoft не собирается изменять своим надежным, проверенным методам борьбы за рынок. Кстати, создаваемые с помощью VS.NET новые Web-элементы будут работать только в среде .NET Framework.

Что же такое Microsoft .NET?

Однозначного ответа на этот вопрос просто нет: очень многое зависит от того, для чего и кому мы его задаем. Ответы представителей Microsoft, Sun, «1С» или ИТ-подразделения ЦБ РФ будут мало похожи один на другой. Тут правомерна аналогия с понятием «разработка приложений»: программист, менеджер проекта и руководитель компании, говоря об этом, будут иметь в виду различный круг решаемых задач.

За последний год в связи с темой .NET мне пришлось посетить много презентаций, услышать кулуарных бесед, прочитать немало статей и целый ряд книг. И мне было очень приятно, когда я наконец-то нашел своего полного единомышленника в том, что касается восприятия стратегии Microsoft. Это известный американский разработчик и публицист Дан Эпплман, чья книга «Переход на VB.NET: стратегии, концепции, код» в начале года вышла в переводе на русский в издательстве «Питер».

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

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

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

«В один прекрасный день выяснилось, что Microsoft начинает отставать от Netscape, Sun и других компаний, занимающихся Интернет-технологиями. Немедленно под фанфары появилась новая технология ActiveX. Что такое ActiveX? Это OLE2 с новым названием».

Поясню: на протяжении более 10 лет деятельность Дана Эпплмана связана с применением технологий Microsoft, он является признанным авторитетом в американском сообществе разработчиков. При этом он подчеркивает: «Противники Microsoft клеймят меня как «продажного наймита», а ее сторонники — осуждают за «злобные нападки». А вот высказывание Эпплмана как раз по поводу обозначенного выше вопроса о сути .NET: «.NET захлестнул тот же поток маркетинговых статей, недостоверных и обрывочных сведений, вольных интерпретаций и неразберихи, от которой пострадали многие инициативы Microsoft. Не думаю, что вы получите сколько-нибудь вразумительный ответ от сотрудников Microsoft — их ответы слишком сильно зависят от должности и от того, какую презентацию PowerPoint им показали последней».

Это было написано год назад. Сейчас, спустя полгода после официального выпуска .NET Framework и Visual Studio .NET, ажиотаж по этому поводу явно пошел на убыль. Это естественно: наступило время проверкой делом маркетинговых заявлений «предстартовой» поры. Но неразбериха в ответе на вопрос «Что такое .NET?» сохраняется и даже усиливается.

Сбывается прогноз двухлетней давности — все новые продукты и технологии Microsoft автоматически получают суффикс .NET независимо от сути используемых в них архитектурных решений. Более того, на одной из презентаций прошедшей весной я видел замечательный слайд, на котором к семейству .NET Server были приписаны задним числом все версии Windows 2000.

Возвращаясь к вопросу, вынесенному в заголовок этого раздела, я даю на него ранее уже озвученный ответ: Microsoft .NET с точки зрения программиста — это новая среда исполнения программного кода, (виртуальная машина) под названием .NET Framework. И, говоря о создании Web-приложений, нужно отметить самое главное новшество: в .NET достигнут значительный прогресс в том, чтобы стереть различия между традиционным программированием под Windows и Интернет-разработкой. Но при этом Microsoft, как обычно, идет своим путем.

Другие статьи из раздела

  • Программная платформа IBM для повышения эффективности бизнеса
  • ИБП для защиты серверов
  • Интегрированное решение для защиты центров обработки данных
  • На пути к построению единой платформы защиты данных
  • Виртуализация без ограничений

Поместить в блог

Комментарии к статье

Рекламные ссылки

Chloride
Демонстрация Chloride Trinergy
Впервые в России компания Chloride Rus провела демонстрацию системы бесперебойного электропитания Chloride Trinergy®, а также ИБП Chloride 80-NET™, NXC и NX для своих партнеров и заказчиков.

NEC Нева Коммуникационные Системы
Завершена реорганизация двух дочерних предприятий NEC Corporation в России
С 1 декабря 2010 года Генеральным директором ЗАО «NEC Нева Коммуникационные Системы» назначен Раймонд Армес, занимавший ранее пост Президента Shyam …

компания «Гротек»
С 17 по 19 ноября 2010 в Москве, в КВЦ «Сокольники», состоялась VII Международная выставка InfoSecurity Russia. StorageExpo. Documation’2010.
Новейшие решения защиты информации, хранения данных и документооборота и защиты персональных данных представили 104 организации. 4 019 руководителей …

МФУ Panasonic DP-MB545RU с возможностью печати в формате А3
Хотите повысить эффективность работы в офисе? Вам поможет новое МФУ #Panasonic DP-MB545RU. Устройство осуществляет

Adaptec by PMC
RAID-контроллеры Adaptec Series 5Z с безбатарейной защитой кэша
Опытные сетевые администраторы знают, что задействование в работе кэш-памяти RAID-контроллера дает серьезные преимущества в производительности …

Chloride
Трехфазный ИБП Chloride от 200 до 1200 кВт: Trinergy
Trinergy — новое решение на рынке ИБП, впервые с динамическим режимом работы, масштабируемостью до 9.6 МВт и КПД до 99%. Уникальное сочетание …

Одностраничные приложения: создание современных адаптивных веб-приложений с помощью ASP.NET

Продукты и технологии:

Single-Page Applications (SPA), ASP.NET Web API, Knockout.js, Ember.js, AJAX и HTML5

В статье рассматриваются:

  • создание уровня сервисов и веб-клиента AJAX для приложения-примера;
  • шаблоны MVC и MVVM;
  • связывание с данными;
  • создание веб-клиента с применением Knockout.js;
  • создание веб-клиента с применением Ember.js.

Одностраничные приложения (Single-Page Applications, SPA) — это веб-приложения, которые загружают одну HTML-страницу и динамически обновляют ее при взаимодействии с пользователем.

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

В этой статье я пошагово пройду процесс создания простого SPA-приложения. Попутно вы ознакомитесь с некоторыми фундаментальными концепциями создания SPA, в том числе с шаблонами Model-View-Controller (MVC) и Model-View-ViewModel (MVVM), связыванием с данными и маршрутизацией (routing).

О приложении-примере

Я создал приложение-пример для операций с простой базой данных по фильмам (рис. 1). В крайнем слева столбце страницы отображается список жанров. Выбор жанра приводит к появлению списка соответствующих фильмов. Кнопка Edit рядом с записью позволяет изменять эту запись. После редактирования можно щелкнуть кнопку Save для передачи обновления на сервер или кнопку Cancel для отмены изменений.

Рис. 1. SPA-приложение для базы данных по фильмам

Я создал две версии этого приложения: одна из них использует библиотеку Knockout.js, а другая — библиотеку Ember.js. Эти две библиотеки основаны на разных подходах, поэтому будет весьма поучительно сравнить их. В обоих случаях клиентское приложение не требовало более 150 строк JavaScript-кода. На серверной стороне я задействовал ASP.NET Web API, чтобы обслуживать JSON для клиента. Исходный код обеих версий вы найдете на github.com/MikeWasson/MoviesSPA.

(Примечание Я создавал приложение, используя RC-версию Visual Studio 2013. В RTM-версии некоторые вещи могли измениться, но они не должны повлиять на код.)

Обзор

В традиционном веб-приложении при каждом вызове сервера тот осуществляет рендеринг новой HTML-страницы. Это вызывает обновление страницы в браузере. Если вы когда-нибудь писали приложение Web Forms или PHP, этот жизненный цикл страниц должен быть знаком вам.

В SPA после загрузки первой страницы все взаимодействие с сервером происходит через AJAX-вызовы. Эти AJAX-вызовы возвращают данные (не разметку) — обычно в формате JSON. Приложение использует JSON-данные для динамического обновления страницы без ее перезагрузки. Рис. 2 иллюстрирует разницу между этими двумя подходами.

Рис. 2. Сравнение традиционного жизненного цикла страницы с жизненным циклом в SPA

Traditional Page Lifecycle Традиционный жизненный цикл страницы
Client Клиент
Page Reload Перезагрузка страницы
Server Сервер
Initial Request Начальный запрос
HTML HTML
Form POST Передача формы командой POST
SPA Lifecycle Жизненный цикл в SPA
AJAX AJAX
JSON JSON

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

Это разделение упрощает проектирование и развитие каждого уровня. В SPA-приложении с тщательно продуманной архитектурой можно изменять HTML-разметку, не касаясь кода, который реализует прикладную логику (по крайней мере, в идеале). Вы увидите это на практике, когда мы будем обсуждать связывание с данными.

В чистом SPA все UI-взаимодействие происходит на клиентской стороне через JavaScript и CSS. После начальной загрузки страницы сервер действует исключительно как уровень сервисов. Клиенту нужно просто знать, какие HTTP-запросы он должен посылать. Ему не важно, как сервер реализует свою часть.

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

Создание проекта в Visual Studio

В Visual Studio 2013 есть один тип проекта ASP.NET Web Application. Мастер этого проекта позволяет выбрать ASP.NET-компоненты, которые будут включены в проект. Я начал с шаблона Empty, а затем добавил в проект ASP.NET Web API, установив флажок Web API в разделе Add folders and core references for, как показано на рис. 3.

Рис. 3. Создание нового ASP.NET-проекта в Visual Studio 2013

В новом проекте есть все библиотеки, необходимые для Web API, а также кое-какой конфигурационный код Web API. Я не вводил никаких зависимостей от Web Forms или ASP.NET MVC.

Обратите внимание на рис. 3, что Visual Studio 2013 включает шаблон Single Page Application. Этот шаблон устанавливает скелет SPA-приложения, основанный на Knockout.js. Он поддерживает вход с применением базы данных с информацией о членстве в группах или с помощью внешнего провайдера аутентификации. Я не стал использовать этот шаблон в своем приложении, потому что хотел показать более простой пример с нуля. Шаблон SPA — отличный ресурс, особенно если вам нужно добавить аутентификацию в приложение.

Создание уровня сервисов

Я использовал ASP.NET Web API, чтобы создать простой REST API для приложения. Не буду здесь вдаваться в детали Web API — подробности вы можете прочитать по ссылке asp.net/web-api.

Сначала я создал класс Movie, представляющий фильм. Этот класс делает две вещи:

  • сообщает Entity Framework (EF), как создавать таблицы базы данных для хранения информации о фильмах;
  • сообщает Web API, как форматировать полезные данные JSON.

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

Затем я воспользовался технологией scaffolding в Visual Studio для создания контроллера Web API, который задействует EF в качестве уровня данных. Чтобы применить эту технологию, щелкните правой кнопкой мыши папку Controllers в Solution Explorer и выберите Add | New Scaffolded Item. В мастере Add Scaffold укажите Web API 2 Controller with actions, using Entity Framework, как показано на рис. 4.

Рис. 4. Добавление контроллера Web API

На рис. 5 приведен мастер Add Controller. Я присвоил контроллеру имя MoviesController. Имя имеет значение, так как URI для REST API основываются на имени контроллера. Я также установил флажок Use async controller actions, чтобы задействовать преимущества новой функциональности async в EF 6. Я выбрал класс Movie в качестве модели и указал New data context, чтобы создать новый контекст данных EF.

Рис. 5. Мастер Add Controller

Мастер добавляет два файла:

  • MoviesController.cs — определяет контроллер Web API, который реализует REST API для приложения;
  • MovieSPAContext.cs — это в основном склеивающий слой EF, который предоставляет методы для запроса нижележащей базы данных.

В табл. 1 показан REST API по умолчанию, создаваемый технологией scaffolding.

Табл. 1. REST API по умолчанию, созданный технологией scaffolding из Web API

HTTP-команда URI Описание
GET /api/movies Получить список всех фильмов
GET /api/movies/ Получить фильм с идентификатором, равным
PUT /api/movies/ Обновить фильм с идентификатором, равным
POST /api/movies Добавить новый фильм в базу данных
DELETE /api/movies/ Удалить фильм из базы данных

Значения в фигурных скобках являются заменителями для подстановки. Например, чтобы получить фильм с идентификатором, равным 5, URI должен выглядеть так: /api/movies/5.

Я расширил этот API, добавив метод, который находит все фильмы указанного жанра:

Клиент указывает жанр в строке запроса URI. Например, чтобы получить все фильмы жанра Drama, клиент посылает GET-запрос на /api/movies?genre=drama. Web API автоматически связывает параметр запроса с параметром genre в методе GetMoviesByGenre.

Создание веб-клиента

До сих пор я просто создавал REST API. Если вы отправите GET-запрос на /api/movies?genre=drama, исходный HTTP-ответ будет выглядеть так:

Теперь мне нужно написать клиентское приложение, которое делает с этим что-то осмысленное. Базовый рабочий процесс такой:

  • UI инициирует AJAX-запрос;
  • обновляем HTML для отображения полезных данных ответа;
  • обрабатываем AJAX-ошибки.

Вы могли закодировать все это вручную. Например, вот некоторый jQuery-код, который создает список названий фильмов:

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

Решение заключается в том, чтобы использовать JavaScript-инфраструктуру. К счастью, их выбор довольно велик, и эти инфраструктуры имеют открытый исходный код. К некоторым из более популярных инфраструктур относятся Backbone, Angular, Ember, Knockout, Dojo и JavaScriptMVC. Большинство использует вариации шаблонов MVC или MVVM, поэтому будет полезно вкратце рассмотреть эти шаблоны.

Шаблоны MVC и MVVM

Корни шаблона MVC уходят в 80-е годы прошлого века и связаны с ранними графическими UI. Цель MVC — разбиение кода на три уровня со своими обязанностями (рис. 6). Вот что они делают:

  • модель представляет данные и бизнес-логику предметной области;
  • представление отображает модель;
  • контроллер принимает пользовательский ввод и обновляет модель.

Рис. 6. Шаблон MVC

View View
Controller Controller
Model Model
User Input Пользовательский ввод
Updates Обновления
Modifies Модифицирует

Более современная вариация MVC — шаблон MVVM (рис. 7). В шаблоне MVVM:

  • модель по-прежнему представляет данные предметной области;
  • модель представления — это абстрактное отражение представления;
  • представление отображает модель представления и посылает пользовательский ввод модели представления.

Рис. 7. Шаблон MVVM

View Model View Model

В JavaScript-инфраструктуре MVVM представлением является разметка, а моделью представления — код.

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

Создание веб-клиента с применением Knockout.js

Для первой версии своего приложения я использовал библиотеку Knockout.js. Knockout следует шаблону MVVM, соединяя представление и модель представления через связывание с данными.

Чтобы создать привязки данных, вы добавляете к HTML-элементам специальный атрибут data-binding. Например, следующая разметка связывает элемент span со свойством genre в модели представления. Всякий раз, когда изменяется значение genre, Knockout автоматически обновляет HTML:

Привязки также могут работать в другом направлении, скажем, если пользователь вводит текст в поле, Knockout обновляет соответствующее свойство в модели представления.

Удобно, что связывание с данными осуществляется декларативно. Вам не требуется подключать модель представления к элементам HTML-страницы. Просто добавьте атрибут data-binding, и Knockout сделает остальное.

Я начал с создания HTML-страницы с базовой разметкой без связывания с данными, как показано на рис. 8.

Рис. 8. Начальная HTML-разметка

(Примечание Я использовал библиотеку Bootstrap для оформления внешнего вида приложения, поэтому в настоящем приложении уйма дополнительных элементов

Создание модели представления

Наблюдаемые объекты (observables) занимают центральное место в системе связывания с данными в Knockout. Наблюдаемым является объект, который хранит какое-то значение и может уведомлять подписчиков об изменении этого значения. Следующий код преобразует JSON-представление фильма в эквивалентный объект с наблюдаемыми полями:

На рис. 9 показана начальная реализация модели представления. Эта версия поддерживает только получение списка фильмов. Средства редактирования я добавлю позже. Модель представления содержит наблюдаемые свойства для списка фильмов, строку ошибки и текущий жанр.

Рис. 9. Модель представления

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

Функция getByGenre выдает AJAX-запрос серверу на получение списка фильмов, а затем заполняет результатами массив self.movies.

При использовании REST API одна из самых хитрых частей — обработка асинхронной природы HTTP. jQuery-функция ajax возвращает объект, реализующий Promises API. Вы можете задействовать метод then объекта Promise, чтобы установить обратный вызов, инициируемый, когда AJAX-вызов завершается успешно, и еще один обратный вызов, запускаемый при неудачном AJAX-вызове:

Привязки данных

Теперь, когда у меня есть модель представления, я могу связать ее с HTML через привязки данных. Для полного списка жанров, который появляется на левой стороне экрана, я использую следующие привязки данных:

Атрибут data-bind содержит одно или более объявлений привязок, где каждая привязка имеет форму «привязка: выражение». В этом примере привязка foreach сообщает Knockout перебирать в цикле содержимое массива genres в модели представления. Для каждого элемента в массиве Knockout создает новый элемент
. Привязка text в присваивает text в span значение элемента массива, каковой в данном случае является названием жанра.

На данный момент щелчок названия жанра ни к чему не приводит, поэтому я добавляю привязку click для обработки событий щелчка:

Это связывает событие щелчка с функцией getByGenre в модели представления. Здесь нужно было использовать $parent, так как эта привязка осуществляется в контексте foreach. По умолчанию привязки в foreach ссылаются на текущий элемент в цикле.

Чтобы отобразить список фильмов, я добавил привязки в таблицу, как показано на рис. 10.

Рис. 10. Добавление привязок в таблицу для отображения списка фильмов

На рис. 10 привязка foreach перебирает в цикле массив объектов movie. Внутри foreach привязки text ссылаются на свойства текущего объекта.

Привязка visible в элементе

контролирует, визуализируется ли таблица. Таблица будет скрыта, если массив movies пуст.

Наконец, вот привязки для сообщения об ошибке и сообщения «No records found» (заметьте, что вы можете помещать в привязку сложные выражения):

Редактирование записей

Последняя часть этого приложения дает возможность пользователю редактировать записи в таблице. Для этого необходима следующая функциональность:

  • переключение между режимами просмотра (только текст) и редактирования (элементы управления вводом);
  • передача обновлений на сервер;
  • поддержка отмены изменений и восстановление исходных данных.

Чтобы отслеживать режим просмотра/редактирования, я добавил булев флаг в объект movie как наблюдаемое свойство:

Мне нужно было, чтобы таблица фильмов отображала текст, когда свойство editing равно false, но переключалась на элементы управления вводом, когда оно — true. Для этого я использовал Knockout-привязки if и ifnot, как показано на рис. 11. Синтаксис « » позволяет включать привязки if и ifnot без их размещения внутри элемента HTML-контейнера.

Рис. 11. Поддержка редактирования записей о фильмах

Привязка value задает значение элемента управления вводом. Это двухсторонняя привязка, поэтому, когда пользователь вводит что-то в текстовое поле или изменяет выбор в раскрывающемся списке, изменение автоматически распространяется на модель представления.

Я связал обработчики щелчка кнопок с функциями save, cancel и edit в модели представления.

Функция edit проста. Достаточно установить флаг editing в true:

Функции save и cancel немного посложнее. Для поддержки отмены мне нужен был какой-то способ кеширования исходного значения при редактировании. К счастью, Knockout упрощает расширение поведения наблюдаемых объектов. В коде на рис. 12 добавляется функция store в класс observable. Вызов функции store из observable придает этому классу две новые функции: revert и commit.

Рис. 12. Расширение ko.observable функциями revert и commit

Теперь я могу вызвать функцию store, чтобы добавить эту функциональность в модель:

Рис. 13 демонстрирует функции save и cancel в модели представления.

Рис. 13. Добавление функций save и cancel

Создание веб-клиента с применением Ember

Для сравнения я написал другую версию своего приложения, используя библиотеку Ember.js.

Ember-приложение начинает с таблицы маршрутизации (routing table), которая определяет навигацию пользователя в рамках приложения:

Первая строка кода создает Ember-приложение. Вызов Router.map создает три маршрута. Каждый маршрут соответствует URI или шаблону URI:

Для каждого маршрута вы создаете HTML-шаблон, используя библиотеку шаблонов Handlebars.

В Ember имеется шаблон верхнего уровня для всего приложения. Этот шаблон подвергается рендерингу для каждого маршрута. На рис. 14 показан шаблон application для моего приложения. Как видите, этот шаблон в основном является HTML-кодом, размещаемым в теге script с type=»text/x-handlebars». Шаблон содержит специальную разметку Handlebars в двойных фигурных скобках: << >>. Эта разметка служит той же цели, что и атрибут data-bind в Knockout. Например, <<#linkTo>> создает ссылку на маршрут.

Рис. 14. Шаблон Handlebars уровня приложения

Теперь допустим, что пользователь переходит к /#/about. Это активирует маршрут about. Ember сначала осуществляет рендеринг шаблона application верхнего уровня, затем шаблона about в <> шаблона application. Вот шаблон about:

На рис. 15 показано, как выполняется рендеринг шаблона about в шаблоне application.

Рис. 15. Рендеринг шаблона about

Поскольку у каждого маршрута свой URI, история браузера сохраняется. Пользователь может осуществлять навигацию кнопкой Back, а также обновлять страницу, не теряя контекст или закладку, и перезагружать ту же страницу.

Контроллеры и модели в Ember

В Ember каждый маршрут имеет модель и контроллер. Модель содержит данные предметной области. Контроллер действует как прокси для модели и хранит все данные состояния приложения для представления. (Это не совпадает с классическим определением MVC. В некоторых отношениях контроллер больше похож на модель представления.)

Вот как я определил модель movie:

Контроллер наследует от Ember.ObjectController (рис. 16).

Рис. 16. Контроллер Movie наследует от Ember.ObjectController

Здесь происходит кое-что интересное. Во-первых, я не указывал модель в классе контроллера. По умолчанию маршрут автоматически устанавливает модель в контроллере. Во-вторых, функции save и cancel используют средства транзакций, встроенные в класс DS.Model. Для отмены изменений просто вызовите функцию rollback модели.

Ember использует массу соглашений по именованию для подключения различных компонентов. Маршрут genres взаимодействует с GenresController, который выполняет рендеринг шаблона genres. По сути, Ember будет автоматически создавать объект GenresController, если вы его не определили. Однако вы можете переопределять все, что предлагается по умолчанию.

В своем приложении я сконфигурировал маршрут genres/movies на использование другого контроллера, реализовав точку подключения (hook) renderTemplate. Тем самым несколько маршрутов может использовать один и тот же контроллер (рис. 17).

Рис. 17. Несколько маршрутов могут иметь общий контроллер

Одна из приятных особенностей Ember в том, что многое можно делать с помощью минимума кода. Мое приложение-пример состоит примерно из 110 строк кода на JavaScript. Эта версия короче, чем версия на основе Knockout, и вдобавок я безо всяких усилий получил поддержку истории браузера. С другой стороны, Ember также является весьма «своенравной» инфраструктурой. Если вы не пишете код в стиле Ember, то скорее всего попадете в неприятности. Так что при выборе инфраструктуры следует принимать во внимание набор функциональности, стиль кодирования и то, насколько общая архитектура инфраструктуры подходит под ваши требования.

Где узнать больше

В этой статье я показал, как JavaScript-инфраструктуры упрощают создание SPA. Попутно я рассказал о некоторых общих средствах этих библиотек, в том числе о связывании с данными, маршрутизации и шаблонах MVC и MVVM. Узнать больше о создании SPA с помощью ASP.NET можно по ссылке asp.net/single-page-application.

Майк Уоссон (Mike Wasson) — программист и технический писатель в Microsoft. Многие годы занимался документированием мультимедийной части Win32 API. В настоящее время пишет о ASP.NET с основным акцентом на Web API. С ним можно связаться по адресу mwasson@microsoft.com.

Выражаю благодарность за рецензирование статьи эксперту Microsoft Хиньяну Чу (Xinyang Qiu).

Asp разработка масштабируемых asp приложений

Начните Ваш проект здесь

Услуги Разработки на ASP.NET

со страстью и гарантией качества

Низкая квалификация команды является одной из причин провала проекта. Только команда с опытом и сильным управлением может уложиться в сроки и сохранить качество. За последние 4 года Merehead выпустила более 95 успешных проектов.

If you want to have a peace of mind that the project will be completed with all the features you wanted I would recommend using this team.
Vitaly Meyer, Co-Founder @ PetroCubic

Сильное общение и регулярные отчеты. Для нас очень важно вести диалог с клиентом, понимать цели и предпочтения. Только так мы сможем построить успешный проект и превзойти ожидания клиентов.

Excellent work!! They built the platform to our satisfaction and were very creative in taking what was simply a series of wireframes and transforming it into a living and breathing e-commerce platform.
Ken Chester, CEO @ JobGrouper LLC

Консультант по развитию бизнеса

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

Merehead is very pleasant to work with, I appreciate Eugene being always available and communicate really well throughout the whole process. If there was something we’d missed he’d just help out and put an end to it.
V Hong Tran, CEO @ Itsdot3

Услуги Разработки на ASP.NET. Наша команда использует все методы и возможности для достижения наилучшего результата.

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

Наша команда не стоит на месте. Мы регулярно улучшаем навыки. Вы не можете получить высокие результаты без навыков.

Весь наш опыт и лучшие практики используются для реализации проектов с неизменно высоким уровнем проектов.

Сильная коммуникация с клиентом и четкое понимание требований позволяют получить идеальный результат.

Мы разрабатывает программное обеспечение в различных отраслях и помогаем компаниям строить эффективный бизнес.

Путешествия и Туризм

Мы строим проекты для туристической индустрии с функциями бронирования, календаря, интеграции покупки авиа- и автобусных билетов.

Мы осуществляем проекты в сфере образования с интегрированной системой управления обучением (LMS).

СМИ и Развлечения

Наша команда разрабатывает медиапроекты с удобной системой управления рекламными блоками на сайте.

Мы предоставляем программные решения в здравоохранении по стандартам HIPAA.

Мы поставляем приложения для электронной коммерции, такие как торговые порталы и чат-роботы в реальном времени

Банки и Финансы

Повышение эффективности благодаря высококачественным программным приложениям корпоративного уровня

PetroCubic дает возможность нанять специалистов для работы над проектом. Это известный тендерный проект для нефтяной и буровой промышленности. Опираясь на разработанные функции, PetroCubic стал популярным в этой области.

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

Отзывы наших клиентов

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

Если у Вас есть вопросы, напишите нам в месенджер.

С 2015 года мы помогаем клиентам реализовать идею в лучший способ.

Услуги Разработки на ASP.NET

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

Команда Merehead обладает большим опытом создания веб-приложений на основе ASP.NET. Для обеспечения максимальной производительности сайтов и повышения уровня бизнеса мы используем весь потенциал данной технологии, включающий такие программы как: ASP.NET 4.5, ASP.NET MVC 4 и ASP.NET Core.

Почему разработчики выбирают ASP.NET

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

Одна из важных особенностей – высокая совместимость с другими языками:
• HTML;
• JS;
• WML и XML;
• VB.NET;
• C#;
• Jscript.NET Visual Studio.

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

Популярность ASP.NET основана на тесной интеграции с сервером Windows. Веб-приложения технологии легче разрабатывать, делать их отладку и развертывание.

Среди других весомых особенностей:
1. Высокая производительность. Данная технология автоматически компилирует код на стороне сервера в DLL-файлы на веб-сервере. Кроме того, производительность повышается за счет использования JIT-компиляции, автоматического управления памятью и обработки исключений.
2. Упрощенная разработка. ASP.NET позволяет сократить объемы необходимого кода для развертывания приложений, что улучшает их масштабируемость. Страницы пишутся намного легче благодаря интеграции с HTML. Кроме того можно легко использовать Angular фреймворк для front-end части проекта.
3. Упрощенное развертывание. Для запуска приложения не нужно регистрировать какие-либо компоненты. Достаточно скопировать его на сервер.
4. Быстрое обновление развернутых приложений без перезапуска сервера.
5. Отличная поддержка мобильных устройств.

Как мы используем потенциал ASP.NET

Платформа предоставляет разработчикам прекрасные возможности для создания эксклюзивных и конкурентоспособных веб-приложений. Но веб-разработка – сложный процесс. Неправильный подход приводит к противоположному результату.

Мы в Merehead решили раскрыть Вам несколько секретов касательно того, как мы выжимаем максимум из ASP.NET.

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

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

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

Для уменьшения потребления ресурсов мы объединяем некоторые соединения. Это значительно снижает негативное влияние на TCP. Таким образом, данные передаются быстрее и без потерь. Помимо снижения потребления ресурсов это также сокращает время, необходимое на разработку.

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

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

Правильное использование «состояния представления». View State в ASP.NET – прекрасная альтернатива памяти сервера и файлам cookie. Но его неправильное использование приводит к потере данных, очень низкой производительности и плохой масштабируемости.

Одно из главных требований использования View State – отключение этого состояния на уровне страницы или уровне контроля. В противном случае значительно повышается время загрузки на этапах обслуживания и при обработке запроса.

ASP.NET для стартапов

Стартапы – не утихающий тренд последних нескольких лет. Для процветания им нужно выбирать правильные технологии. В этом плане они часто полагаются именно на PHP разработку или ASP.NET. Почему? Приложения, закодированные с помощью этой платформы, высоко ценятся крупными компаниями, которые часто выступают инвесторами. А кто, как не инвестор, нужен начинающему проекту?

Для закрепления позиций на рынке и развития будущего успеха стартапа ASP.NET предлагает множество безупречных функций.

Приложения ASP.NET «работают на стероидах». Структура кода столь великолепна, что надежность становится основной характеристикой приложений. Благодаря координации с HTML разработчики могут обеспечить необходимые показатели, вроде высокой скорости отклика или плавной загрузки страницы.

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

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

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

ASP.NET для E-Commerce

Электронная коммерция – еще один тренд. Но она создает новые проблемы, среди которых угроза личным данным клиентов магазинов, а также опасность незаконных транзакций. ASP.NET – одно из решений, которое позволит делать покупки онлайн без какой-либо угрозы.

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

Второе – простой интерфейс, который позволит клиенту быстро найти желаемый товар. Чем быстрее он справится, тем больше удовольствия получит. Значит захочет вернуться.

Третье – удобное администрирование и управление контентом. Пара простых манипуляций необходима для таких частых действий, как добавление/удаление товара или изменение цены. Таким образом, ASP.NET помогает обеспечить более высокую степень удовлетворенности клиента.

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

Что же остается за Вами? Нанять хороших разработчиков. Команда Merehead в этом поможет. Сделайте свой бизнес лучшим.

Asp разработка масштабируемых asp приложений

Данные советы вводят в проблему повышения производительности работы приложений, использующих технологии Microsoft Active Server Pages (ASP) и Visual Basic Scripting Edition (VBScript). Большинство из них были многократно обсуждены и c успехом проверены на практике и будут интересны как новичкам в программировании ASP и VBScript, так и тем, кто уже имеет опыт работы с этими технологиями. При подготовке советов был использованы материалы c веб-сайта корпорации Microsoft Corp. (http://www.microsoft.com) и материалы конференций Relib.com (http://www.relib.com)

Совет 1: Кэшируйте часто используемые данные на сервере

Типичная ASP-страница получает данные из базы данных и затем выводит их в формате HTML. Независимо от скорости работы вашей базы данных, получение данных из памяти сервера будет намного быстрее, чем обработка sql-запроса к конечной базе данных. Получение данных, сохраненных на локальном жестком диске сервера, также обычно быстрее, чем получение информации из БД. Поэтому одним из основных путей увеличения скорости работы вашей ASP-страницы является кэширование часто используемой информации в памяти или на жестком диске.

Кэширование данных — это классический компромисс «место или время». Если вы избрали для кэширования правильный материал, вы можете видеть внушительное повышение производительности вашего приложения. Чтобы кэширование было эффективным нужно использовать для временного хранения только те данные, которые многократно используются для вывода и каждый раз трудоемки для повторных вычислений. Кэш, полный устаревшей информации, будет пустой тратой памяти сервера.

Данные, которые изменяются не часто, будут хорошим кандидатом для кэширования, потому что вам не надо будет волноваться относительно их синхронизации через какое-то время с конечной базой данных. Выпадающие списки (сombo-box), таблицы ссылок, пункты меню, и переменные конфигурации сайта (включая имена DSN, адреса IP и URL) — первые кандидаты для хранения в кэше. Заметьте, что вы можете кэшировать представление данных много быстрее, нежели данные сами себя. Если ASP-страница изменяется не так часто и ее временный кэш будет весьма внушительным (например, полный каталог изделий фирмы), попробуйте использовать сгенерированные HTML-страницы, чем каждый раз загружать сервер генерацией ASP-страниц.

Совет 2: Кэшируйте часто используемые данные в объектах Application или Session

Объекты Application и Session служат для хранения данных в памяти, значения которых могут быть доступны между несколькими HTTP-запросами (в отличие от обычных переменных, чьи значения доступны только в теле одной ASP-страницы). Данные объекта Session доступны только одному пользователю (в течении его сессии), в то время как данные Application доступны всем пользователям веб-сайта. Поэтому часто перед разработчиком возникает вопрос: в каком из объектов сохранять часто используемые данные. Обычно, для инициализации переменных этих объектов используются процедуры файла Global.asa — Application_OnStart() или Session_OnStart() соответственно. Если в вашем Global.asa еще нет этих процедур, то вы можете добавить их сами или инициализировать переменные, когда это будет необходимо. Примером может быть следующая процедура, использующая Application для хранения значений многократно использующейся переменной EmploymentStatusList. Процедура проверяет существование данных в EmploymentStatusList и при необходимости расчитывает их заново:

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

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

Совет 3: Кэшируйте данные на диске веб-сервера

Иногда в памяти вашего веб-сервера может быть слишком большое количество данных. «Слишком много», конечно, является спорным вопросом — это зависит от того, сколько памяти вы хотите использовать, а также число элементов для кэширования и частота, с которой эти элементы будут запрашиваться. В любом случае, если вы имеете слишком большое количество данных для кэширования в памяти, подумайте о переносе кэша в текстовый или XML-файл на жесткий диск веб-сервера. Вы можете одновременно комбинировать кэширование на диске и в памяти, чтобы сформировать оптимальную стратегию для вашего сайта.

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

ASP и COM обеспечивают несколько инструментальных средств для создания схем кэширования на диске. Функции набора записей ADO Save() и Open() сохраняют и загружают recordset c диска. Используя эти методы вы можете переписать код из прошлого совета, заменяя запись в объект Application на метод Save() для записи в файл.

Есть несколько других компонентов, которые работают с файлами:

  • Scripting.FileSystemObject позволяет создавать, читать и записывать файл.
  • MSXML, MicrosoftR XML parser поддерживает сохранение и загрузку XML-документов.
  • Объект LookupTable (например, используемый на MSN.com) — лучший выбор для загрузки простых списков с диска.

Наконец, рассмотрите вопрос принудительного кэширования информации на диске. Сгенерированный HTML-код может быть сохранен на диске как .htm или .asp файл; гиперссылки могут указывать прямо на этот файл. Вы можете автоматизировать процесс генерации HTML, используя коммерческие инструментальные средства типа XBuilder или средства публикации в Интернет, входящие в MicrosoftR SQL ServerT. Кроме того, при помощи директивы #include можно включать отдельные HTML-части в файл ASP или читать HTML-файл с диска используя FileSystemObject. Например, на начальной странице веб-сайта Relib.com (http://www.relib.com/index.asp) приводятся 2 списка последних тем обсуждения двух дискуссионных форумов этого сайта. Отобразить эти списки можно при помощи создания двух наборов записей ADO при каждом обращении к данной странице или, следуя данному совету, сохранить их однажды в виде HTML-файла list.inc, а затем включать в index.asp:

Второй путь работает значительно быстрее.

Совет 4: Избегайте кэшировать медленные компоненты в объектах Application или Session

Несмотря на то, что кэшированиe данных в объектах Application или Session может быть хорошей идеей, кэширование COM-объектов может иметь серьезные ловушки. Занесение наиболее используемых COM-объектов в объекты Application или Session часто соблазняет, но, к сожалению, много COM-объектов, включая все, написанные в Visual Basic 6.0 или ранее, могут вызывать серьезные критические проблемы после сохранения в объектах Application или Session.

В частности, любой компонент, который выполняется медленно, вызовет критические проблемы когда кэшируется в объектах Session или Application. Быстрый (проворный non-agile) компонент — компонент, помеченный ThreadingModel=Both, который объединен Free-threaded marshaler (FTM), или — компонент, помеченный ThreadingModel=Neutral. (Neutral — новая модель в WindowsR 2000 and COM+). Следующие компоненты не проворны:

  • Free-threaded components.
  • Apartment-threaded components.
  • Single-threaded component.
  • Configured components (библиотека Microsoft Transaction Server (MTS)/COM+ и серверные приложения) не проворны пока они Neutral-threaded. Apartment-threaded components и другие не проворные компоненты хорошо работают в пределах страницы (т.е. создаются и разрушаются в пределах одной ASP-страницы).

В IIS 4.0 компонент, отмеченный ThreadingModel=Both выполняется быстро. В IIS 5.0 уже не так достаточно. Компонент не должен только быть отмечен как Both, он должен также объединен FTM.

IIS выполняет проверку компонентов, но если вы хотите ее отменить (т.е. хотите позволить непроворным компонентам быть сохраненными в объектах Application или Session), вы можете установить AspTrackThreadingModel в metabase в значение True. Но это (изменение AspTrackThreadingModel) не рекомендуется.

IIS 5.0 выдаст сообщение об ошибке, если Вы пытаетесь сохранить непроворный компонент, созданный с использованием Server.CreateObject, в объекте Application. Вы можете обойти это, используя в Global.asa, но это также не рекомендуется, поскольку это ведет к проблемам (очереди и сериализация), объясняемым ниже.

Что же все-таки неправильно если вы кэшируете непроворные компоненты? Непроворный компонент, кэшируемый в объекте Session блокирует Session от других рабочих потоков (thread) ASP. ASP обслуживает пул (контейнер) рабочих потоков, запрашиваемых другими сервисами. Обычно, новый запрос обрабатывается первым доступным потоком. Если Session блокирована, то запрос должен ждать поток, когда он станет доступным. Проведем аналогию, которая поможет понять эту ситуацию: вы идете в магазин, выбираете несколько булок, и платите за них в кассе #3. Всякий раз, после того как вы выбрали булки в том магазине, вы всегда оплачиваете их в кассе #3, даже в том случае, когда в других кассах короче очередь или даже вообще нет покупателей.

Сохранение непроворных компонентов в объект Application накладывает столь же негативный эффект на производительность. ASP создает специальный поток для выполнения меделенных компонентов в пределах Application. Это имеет два последствия: все запросы выстраиваются в очередь к этому потоку и все запросы сериализуются. Выстраивание в очередь означает, что параметры были сохранены в общедоступной области памяти; запросы переключаются к специальному потоку; метод компонента выполнен; результаты выстраиваются в общедоступную область. Сериализация (преобразование в последовательную форму) означает, что все методы выполняются в одно время. Для двух различных потоков ASP не возможно одновременное выполнение методов общедоступного компонента. Это уничтожает многопотоковость (параллелизм), особенно на мультипроцессорных системах. Хуже всего то, что все непроворные компоненты в пределах Application совместно используют один поток («Host STA»), так что негативные результаты сериализации налицо.

Смущены? Есть некоторые общие правила. Если Вы пишете объекты в Visual Basic (6.0 или ранее), не храните их в объектах Application или Session. Если вы не знаете потоковую модель объекта, не храните его в кэше. Вместо кэширования где-либо непроворных объектов, вы должны создать и удалить их на каждой странице. Объекты выполнятся непосредственно в рабочем потоке ASP и не будет никакой очереди или сериализации. Производимость будет адекватна, если COM-объекты запущены под IIS и если они не используют много времени, чтобы инициализироваться и уничтожаться. Заметьте, что однопотоковые (single-threaded) объекты не должны использоваться этот путь. Будьте внимательным — VB может создавать однопотоковые объекты! Если вы используете однопотоковые объекты, этот путь (типа таблицы Microsoft Excel) не рассчитывает на высокую производительность.

Наборы записей (recordset) ADO могут безопасно кэшироваться когда ADO отмечен как Free-threaded. Чтобы сделать ADO как Free-threaded используйте файл Makfre15.bat, который обычно зафиксирован в каталоге \\Program Files\Common Files\System\ADO.

Предупреждение: ADO не должен быть Free-threaded, если вы используете Microsoft Access в качестве БД. Набор записей ADO должен быть также вообще отсоединен, если вы не можете управлять конфигурацией ADO на вашем веб-сайте.

Совет 5: Не кэшируйте соединение БД в объектах Application или Session

Кэширование соединений ADO — обычно является плохой стратегией при разработке ASP-сайта. Если один объект Connection сохранен в объекте Application и используется на всех страницах, то все страницы будут бороться за использование этого соединения. Если объект Connection сохранен в ASP-объекте Session, то соединение БД будет создано для каждого пользователя. Это создает излишнюю загрузку веб-сервера и БД.

Вместо кэширования соединений БД, создавайте и уничтожайте объекты ADO на каждой ASP странице, которая использует ADO. Это эффективно, потому что IIS имеет встроенное подключение БД. Более точно, IIS автоматически допускает объединение подключений OLEDB и ODBC. Это гарантирует, что создание и уничтожение связей на каждой странице будут эффективны.

Так как соединенные наборы хранят ссылки на подключение БД, это следует, что вы должны не кэшировать соединенные наборы в объектах Application или Session. Однако, вы можете безопасно кэшировать отсоединенные наборы, которые не держат ссылку на подключение. Чтобы отсоединить набор записей, сделайте следующие два шага:

Совет 6: Разумное использование объекта Session

Теперь, когда в предыдущих советах были раскрыты достоинства кэширования данных в объектах Applications и Sessions, вам предлагается пытаться избегать использования объекта Session. Сессии имеют несколько ловушек когда используются на загруженных сайтах. Под «загруженными» имеются ввиду сайты с сотнями запрашиваемых страниц в секунду или тысячами пользователей одновременно. Этот совет также важен для сайтов, которые должны масштабироваться горизонтально — т.е. те сайты, которые используют несколько серверов для распределения нагрузки и обеспечения отказоустойчивости при сбоях. Для меньших сайтов, типа intranet-сайтов, преимущества применения Sessions все же перевешивают.

Обобщая, ASP автоматически создает Session для каждого пользователя, который обращается к веб-серверу. Каждая сессия занимает приблизительно 10 Кб памяти (сверх любых данных, сохраненных в Session) и немного замедляет выполнение всех запросов. Сессия остается действующей до окончания таймаута (timeout), обычно 20 мин.

Но самая большая проблема при использовании сессий — это не производительность, а расширяемость. Сессии не охватывают все задействованные веб-сервера; как только Session была создана на одном сервере ее данные остаются там. Это означает, что если вы используете сессии на мультисерверном веб-сайте, вы должны придумать стратегию для обработки запросов каждого пользователя, которые должны быть всегда направлены на сервер, на котором существует сессия этого пользователя. Это называется «застреванием» пользователя на сервере (или «липкой сессией»).

Объект Application также не охватывает все сервера: если вам нужно совместно использовать и обновлять данные Application через веб-сервера, вам нужно использовать конечную базу данных. Однако неизменяемые (read-only) данные Application все же полезны на мультисерверных сайтах.

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

Если же вы не используете Session, то убедитесь, что отключили их. Это можно сделать посредством Internet Services Manager (см. документацию по ISM). Но если вам все-таки необходимо использовать сессии, то есть несколько путей уменьшить их удары про производительности.

Вы можете переместить содержимое, которое не требует сессий (например, страницы help и т.д.) в отдельное ASP-приложение, у которого сессии выключены. Кроме того, на страницах, где объект Session не используется, применяйте следующую директиву, помещещаемую вверху страницы:

Одна из основных причин ее применения — то, что Session создает интересную проблему в случае использования фрэймов (frameset). ASP гарантирует, что в любое время будет выполняться только один запрос от Session. Это делается для того, чтобы при одновременном запросе одним пользователем нескольких страниц, только один ASP-запрос был обработан сессией, что помогает избежать проблем многопоточного доступа к объекту Session. К сожалению, в результате этого все страницы в frameset будут загружаться последовательно, а не одновременно, и пользователю придется продолжительное время ждать полной загрузки. Мораль этой истории: если вы не уверены, что с использованием фрэймов и Session ваше приложение правильно работает, то используйте:

Альтернативой использованию объекта Session являются многочисленные параметры управления Session. При передаче малых объемов данных (менее 4 Кб) обычно рекомендуется использовать Cookies, переменные QueryString и скрытые (h >Если в вашем приложении используется много функций VBScript или JScript, то зачастую производительность можно улучшить поместив этот код в откомпилированный COM-объект. Обычно откомпилированная программа выполняется значительно быстрее, чем интерпретируемый код, поэтому откомпилированные COM-объекты будут работать более эффективно, чем вызываемые методы скрипта.

Выделение (инкапсуляция) кода в COM-объект имеет следующие преимущества (не считая производительности):

  • COM-объекты хороши для логического представления структуры приложения.
  • COM-объекты позволяют многократное использование одного кода.
  • Много разработчиков находят код, написанный в VB, C++ или Visual J++ проще в отладке, чем ASP.

Но наряду с, казалось бы, неоспоримыми достоинствами COM-объекты имеют и недостатки, среди которых — время разработки и потребность в различных навыках программирования. Будьте уверены, что инкапсуляция в малых ASP-приложениях может вызвать скорее убытки, чем прибыль. Обычно это случается, когда маленькое количество ASP-кода переносится в объект COM. В этом случае накладные расходы от создания и вызова этого объекта перевешивают выгоду от использования интерпретируемой программы. Определить наиболее выигрышную комбинацию для производительности — использование сценариев ASP или COM-объектов — можно только методом проб и ошибок. Заметим, что Microsoft значительно улучшила ASP-сценарии и производительность ADO в Windows 2000/IIS 5.0 по сравнению с Windows NT 4.0/IIS 4.0. Таким образом, преимущество откомпилированного кода над кодом ASP уменьшилось с введением IIS 5.0 и ваше приложение должно работать быстрее, по сравнению с четвертой версией IIS.

Совет 8: Объявляйте переменные поздно, а удаляйте рано

Данный совет небольшой, но не менее важный в оптимизации ASP, чем все предыдущие. Суть его в следующем: лучше всего объявлять переменные только по мере необходимости и сразу удалять их, как только они становятся ненужными. Это относится и к COM-объектам и к указателям открываемых файлов и другим используемым ресурсам.

Соединения (Connection) ADO и рекордсеты — первостепенные кандидаты для этой оптимизации. Использовав recordset или сonnection для отображения данных сразу же удаляйте эти переменные из памяти, не дожидаясь конца страницы. Не позволяйте рекордсету или соединению остаться незакрытыми.

Например, если вы создаете соединение и открываете набор записей следующим образом:

то закройте их вот так:

Любые другие переменные Microsoft VBScript также лучше устанавливать в Nothing.

Совет 9: Out-of-process как компромисс между производительностью и надежностью

И ASP и MTS/COM+ имеют параметры конфигурации, которые позволяют вам выбрать альтернативу между надежностью и производительностью. Вы должны сделать разумный выбор при разработке ваших ASP-приложений.

Работа ASP-приложений может быть сконфигурирована одним из трех путей. В IIS 5.0 введен термин «уровень изоляции» (isolation level), описывающий эти пути, и который делится на три уровня — Low (низкий), Medium (средний), и High (высокий):

Low Isolation. Поддерживается во всех версиях IIS и самый быстрый. Он выполняет ASP в Inetinfo.exe, который является первичным процессом IIS. Если ASP-приложение дает сбой, то нагрузка ложится на IIS. (Чтобы перезапутить IIS под IIS 4.0 вебмастер должен был вести мониторинг сайта, используя инструменты типа InetMon, и рестартовать его командным файлом, если на сервере произошел сбой. В IIS 5.0 введена более надежная функция рестарта, которая автоматически перезапускает сервер в случае сбоя.)

Medium Isolation. Этот новый уровень, впервые введенный в IIS 5.0, называют out-of-process, т.к. ASP выполняется вне процесса IIS. В Medium Isolation все приложения ASP сконфигурированы для выполнения как среднеразделенный процесс. Это уменьшает число процессов, требуемых для загрузки нескольких ASP-приложений out-of-process. В IIS 5.0 уровень Medium Isolation установлен по-умолчанию.

High Isolation. Поддерживающийся в IIS 4.0 и IIS 5.0 уровень High Isolation также выполняется out-of-process. Если в ASP произошел сбой, то с веб-сервером ничего не случится — ASP-приложение автоматически перезапускается со следующим запросом ASP. В High Isolation, каждое ASP-приложение сконфигурировано для выполнения в собственном участке памяти, что защищает приложения ASP от друг друга (отсюда и название — «высокая изоляция»). Недостаток этого — требование раздельных процессов для каждого ASP-приложения.

Вы спросите, который уровнь лучше? В IIS 4.0 выполнение out-of-process сказывалось довольно негативно на производительности. В IIS 5.0 было проделано много работы для уменьшения последствий от запущенных out-of-process ASP-приложений. Фактически в большинстве испытаний ASP-приложения, запущенные out-of-process под IIS 5.0, выполняются быстрее, чем под IIS 4.0. Независимо от этого, Low Isolation все еще предоставляет лучшую производительность на обеих платформах. Однако, вы не увидите большой выгоды от Low Isolation, если ваш веб-сервер имеет низкую нагрузку. Поэтому, вам не стоит устанавливать этот уровень, до тех пор, пока ваш сервер не будет выполнять запросы в сотни или даже тысячи страниц в секунду. Как всегда, испытание с различными конфигурациями и определяет наиболее лучший выбор.

Заметим, что когда вы выполняете ASP-приложения out-of-process (уровни Medium или High), они выполняются в MTS под NT4 и COM+ под Windows 2000. Т.е. под NT4 они выполняются в Mtx.exe, а под Windows 2000 они выполняются в DllHost.exe. Вы можете увидеть эти процессы запустив Администратор Задач (Task Manager). Вы можете также увидеть как IIS компонует пакеты MTS или приложения COM+ для out-of-process приложений ASP.

Компоненты COM также имеют три параметра конфигурации, хотя они и не полностью аналогичны параметрам настройки ASP. Компоненты COM могут быть: «неконфигурированными» (unconfigured), настроенными как библиотечные или серверные приложения. «Неконфигурированные» — т.е. компонент не зарегистрирован с COM+. Такой компонент будет выполниться в памяти вызывающего процесса, т.е. «in-process» («в процессе»). Библиотечные приложения (Library Applications) также выполняются in-process, но имеют выгоду от сервисов COM+, включая защиту, транзакции и контекстную поддержку. Серверные приложения выполняются в собственной памяти процесса.

Вы сможете увидеть весьма небольшую выгоду неконфигурированных компонентов над библиотечными приложениями. И, вероятно, большую производительность библиотечных приложений над серверными. Это все потому, что библиотечные приложения выполняются в том же самом процессе, что и ASP, в то время как серверные приложения выполняются в их собственном процессе — межпроцессорные запросы более трудоемки, чем работа в in-process (например, при обмене данными recordset между процессами, все данные должны быть скопированы из одного процесса в другой).

Так что же все-таки использовать?

Если вам требуются конфигурации с разумными долями реализации производительности и надежности, то советуем вам следующее: под IIS 4.0 используйте Low Isolation level и MTS Server Packages, под IIS 5.0 используйте Medium Isolation level и COM+ Library Applications. Но учтите, что данный совет — очень общая рекомендация. Например, хостинговые компании обычно устанавливают Medium или High Isolation level, тогда как множество веб-серверов могут работать в Low Isolation. Так что, лучше всего попробовать самому и решить, которая конфигурация непосредственно для вас наилучшим образом выполняет ваши потребности.

Совет 10: Используйте директиву Option Explicit

Используйте директиву Option Explicit в ваших .asp файлах. Расположенная в самом верху .asp файла, она заставляет разработчика объявлять все переменные, которые он использует. Многие программисты считают, что это позволяет быстрее отлаживать приложения, исключая, таким образом, ошибки в написании имен переменных и невнимательное создание новых переменных (например, MyXLMString=. вместо MyXMLString=).

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

Таким образом, использование директивы Option Explicit гарантирует, что все используемые переменные объявлены и доступ к ним будет максимально быстрым.

Совет 11: Используйте локальные переменные в подпрограммах и функциях

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

Совет 12: Копируйте частоиспользуемые данные в переменные

При вызове COM в ASP, вы должны копировать частоиспользуемые данные объекта в переменные ASP-скрипта. Это сократит количество запросов методов COM, которые являются относительно трудоемкими по сравнению с обращением к переменным самого скрипта. При вызове объектов Collection и Dictionary этот совет также сокращает время запросов.

Вообще, если вы пользуетесь объектом данных больше, чем однажды, поместите данные в переменную ASP-скрипта. Главной целью этой оптимизации являются переменные объекта Request (Form и QueryString). Например, на вашем веб-сайте через QueryString передается переменная UserID. Предположите, что этот UserID упомянут дюжину раз на каждой странице. Вместо вызова Request(«UserID») 12 раз, поместите этот UserID в какую-либо переменную наверху ASP страницы и затем используйте эту переменную (а не Request) внутри страницы. Это упразднит 11 COM-запросов!

На практике, доступ к свойствам или методам COM может быть обманчиво дорог. Посмотрите пример, показывающий некоторый обычный код:

Когда этот код выполняется, происходит следущее:

  1. Переменная Foo получена как глобальный объект.
  2. Переменная bar получена как член Foo. Это оказывается запросом COM-метода.
  3. Переменная blah получена как член Foo.bar. Это также оказывается запросом COM-метода.
  4. Переменная qaz получена как член foo.bar.blah. Да, это также оказывается запросом COM-метода.
  5. Вызовите Foo.bar.blah.quaz(1). Еще один запрос COM-метода. Представляете?
  6. Сделайте шаги от 1 до 3 снова, чтобы получить baz. Система не знает, изменил запрос к qaz модель объекта, так что шаги 1 до 3 должны быть выполнены снова, чтобы получить baz.
  7. Получите baz как член Foo.bar.blah.
  8. Сделайте шаги от 1 до 3 снова и получите zaq.
  9. Сделайте шаги от 1 до 3 уже в другой раз и получите abc.

Как видите это ужасно неэффективно (и медленно). Быстрый способ — написать этот код в VBScript: ,pre> Set myobj = Foo.bar.blah ‘Объявляем blah однажды! Myobj.baz = myobj.qaz(1) If Myobj.zaq = Myobj.abc Then ‘.

Если вы используете VBScript 5.0, то можете использовать выражение With:

Совет 13: Избегайте использования переопределяемых массивов

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

Пример ниже показывает использование беспричинного использования Dim и Redim.

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

Совет 14: Используйте буферизацию Response

Вы можете буферизировать целую страницу, включив «response buffering». Это минимизирует количество записей в браузер и, таким образом, улучшит производительность. Каждая запись имеет много непроизводительных издержек (и в самом IIS и в том количестве данных, посланных по проводам), так что меньшее количество записей будет лучше. TCP/IP работает намного более эффективно когда возможно посылать несколько больших блоков данных, чем при пересылке многочисленных маленьких блоков (из-за медленного начала процесса пересылки и сложных алгоритмов проверки).

Есть два пути использования «response buffering». Первый путь — вы можете включить response buffering для приложения, взятого в целом, используя Internet Services Manager. Это рекомендуемый подход, поэтому response buffering включен по-умолчанию для новых ASP-приложений в IIS 4.0 и IIS 5.0. Второй путь — вы можете активировать буферизацию, поместив следующую линию кода вверху ASP-страницы:

Эта линия кода должна быть выполнена прежде, чем любые данные response был записаны в браузер (т.е. прежде, чем появится любой код HTML в ASP-скрипте и прежде, чем были установлены любые Cookies, используя Response.Cookies). Вообще, лучше включить response buffering, как указано в первом случае. Это позволит вам избежать применения вышеупомянутой линии кода в каждой странице.

Есть только одна общая проблема относительно буферизации Response — то, что пользователи чувствуют ASP-страницы менее «отзывчивыми» (даже при том, что время полного получения готовой страницы получается меньше) потому что они должны ждать полную страницу, которая будет произведена прежде, чем, они начинают видеть что-нибудь. Для длинных страниц, вы можете выключить буферизацию, установив Response.Buffer = False. Однако, лучшей стратегией будет использование метода Response.Flush. Этот метод показывает весь HTML, который был записан ASP в браузер. Например, после записи 100 строк из таблицы с 1000-ю записей, ASP может вызывать Response.Flush, чтобы вынудить показать браузер уже готовые 100 строк; это позволяет пользователю увидеть первые 100 строк таблицы прежде, чем остальные строки будут будут получены.

(Заметьте, что в вышеупомянутом примере таблицы с тысячью записей некоторые браузеры не будут отображать таблицу, пока они не получат заключительный HTML-тег

. Так что проверьте ваш браузер на этот счет. Чтобы обойти эту проблему, попробуйте разделить таблицу на несколько более меньших таблиц (с меньшим количеством строк) и вызывать Response.Flush после каждой из них. Новые версии Internet Explorer отображают таблицы прежде, чем они полностью закончены и будут показывать их еще быстрее, если вы определите ширину столбцов таблицы — это поможет избежать расчетов, которые требуются браузеру для самостоятельного вычисления ширины столбцов путем измерения длины строк данных в каждой ячейке таблицы.

Другая обычная проблема с буферизацией Response — то, что она может использовать много серверной памяти при генерации очень больших страниц. Если вам необходимо генерировать такие страницы, то совет будет тем же — попробуйте сочетать буферизацию и Response.Flush.

Совет 15: Группируйте однолинейный код и выражения Response.Write

Однолинейная конструкция VBScript записывает значение «выражения» в исходящий ASP-поток. Если буферизация response не включена (см. Совет 14), то при частом использовании таких выражений, каждое из них приведет к записи данных в браузер путем передачи по сети множества маленьких пакетов, что выполняется медленно. Точно также производительность приложения снижается при частом чередовании маленьких кусочков ASP-кода и HTML. Поэтому данный совет состоит в следующем: замените рядом стоящие однолинейные конструкции одним вызовом Response.Write. Например, в следующем примере отображения таблицы БД показано необоснованно частое переключение в каждой строке между однолинейным кодом VBScript и тэгами HTML:

Ниже приводится более эффективный код, содержащийся в едином блоке VBScript и призванный ускорить отображение данных:

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

Совет 16: Используйте Response.IsClientConnected перед получением больших объемов данных

Если пользователь нетерпелив и торопится, он может отказаться от вашей просмотра ASP-страницы прежде, чем вы начнете выполнять его запрос. Если он нажал в браузере Refresh или ушел на другую страницу вашего сервера, вы получите новый запрос, стоящий в конце очереди ASP-запросов и «отсоединенный» запрос, стоящий в середине очереди. Часто это случается когда ваш сервер сильно загружен (имеет длинную очередь запросов с, соответственно, большим временем ответа) и этот новый запрос делает ситуацию еще хуже. Нет никакого смысла выполнять ASP-скрипт (особенно медленный и тяжеловесный), если пользователь больше не соединен со своим запросом. Вы можете проверить это состояние, используя свойство Response.IsClientConnected. Если оно возвращает False вы должны вызвать Response.End и отказаться от получения остальной части страницы. Фактически, IIS 5.0 использует эту практику — всякий раз, когда ASP собирается выполнять новый запрос, он проверяет, чтобы увидеть как долго запрос был в очереди. Если он был там более, чем 3 секунд, ASP проверит, соединен ли все еще клиент и немедленно закончит запрос, если нет. Вы можете использовать AspQueueConnectionTestTime, чтобы установить этот таймаут в 3 секунды.

Если вы имеете страницу, которая требует очень много времени для выполнения, вы можете проверять Response.IsClientConnected на разных стадиях выполнения. Когда буферизация активирована — хорошая идея также вызывать Response.Flush, чтобы дать понять пользователю, что что-что работает.

Обратите внимание, что в IIS 4.0 Response.IsClientConnected не будет правильно работать, если вы сначала не делаете Response.Write. Если буферизация активирована вы будете также должны делать Response.Flush. На IIS 5.0 нет никакой потребности в этом — Response.IsClientConnected работает прекрасно. В любом случае Response.IsClientConnected требует некоторых затрат времени, поэтому используйте ее только перед действием, которое требует, скажем, по крайней мере, не менее 500 миллисекунд (это большой промежуток времени, если у вас большая нагрузка на сервер). Т.е. вы должны отдавать себе отчет в действиях и не вызывать Response.IsClientConnected перед выводом каждой строки таблицы БД, гораздо лучше будет, если такая проверка будет реже, возможно, перед выводом новых 20-ти или 50-ти строк.

Совет 17: Объявляйте объекты используя тег

Если вам нужно обращаться к объектам, которые затем могут быть не использованы в коде (особенно объекты, содержащиеся в объектах Server или Application), попробуйте объявлять их в global.asa используя следующий синтакс:

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

Совет 18: Используйте объявления TypeLib для ADO и других компонентов

При использовании ADO разработчики часто включают adovbs.txt чтобы получить доступ к различным константам ADO. Этот файл должен быть включен в каждую страницу, в которой нужно использовать эти константы. Но этот файл констант достаточно большой и увеличивает время трансляции каждой ASP-страницы и размер скрипта.

В IIS 5.0 введена способность связать с библиотекой типов компонента, которая позволяет вам один раз сослаться на библиотеку типов и использовать ее на каждой ASP-странице. Причем в каждой странице не надо будет компилировать файл констант и разработчикам компонентов не надо формировать файлы VBScript #include для использования в ASP.

Чтобы обращаться к ADO TypeLib разместите одно из следующих выражений в Global.asa:

Совет 19: Пользуйтесь преимуществами клиентской проверки правильности данных

Современные браузеры имеют широко развитую поддержку XML, DHTML, java-апплетов и Remote Data Service. Пользуйтесь преимуществами этих возможностей всякий раз, когда можете. Все эти технологии помогают сократить на запросах к серверу и обратно, выполняя клиентскую проверку правильности ввода данных (например, проверку, имеет ли кредитная карта правильную контрольную сумму и т.п.). Сократив на обращениях клиент-сервер, вы снимите дополнительную нагрузку с сервера, тем самым — сократите сетевой траффик (хотя начальная страница, посланная браузеру, скорее всего будет большей), а также снизите нагрузку с любых других конечных ресурсов, к которым обращается ваш север (базы данных и пр.). Кроме того, пользователю не надо будет ждать новую страницу с сообщением об ошибке и предложением вернуться назад. Однако все это не означает, что вам надо просто перенести всю вашу проверку с сервера на клиента, нет. Вы должны всегда делать проверку вводимых данных на сервере, потому что она поможет защитить против хакеров или браузеров, которые не поддерживают ваши клиентские процедуры проверки.

Много было сделано для создания HTML, «независимого от браузера». Это часто препятствует разработчику при извлечении выгоды от популярных особенностей браузеров, которые могли бы приносить пользу. Для высокопроизводительных веб-сайтов, которые беспокоятся о «досягаемости» для браузеров, хорошей стратегией будет оптимизация страниц под наиболее популярные программы просмотра. Особенности браузера могут быть легко обнаружены в ASP используя Browser Capabilities Component («компонент возможностей браузера»). Инструментальные средства типа Microsoft FrontPage могут помочь вам при проектировании кода, который будет работать с теми браузерами и версиями HTML, которые вы хотите.

Совет 20: Избегайте конкатенации строк в циклах

Множество программистов делают образование строк в циклах следующим образом:

В таком подходе есть несколько проблем. Во-первых, неоднократная конкатенация (соединение) строк берет квадратичное время или если сказать менее формально, то — время, которое потребуется на выполнение цикла, пропорционально квадрату количества записей к числу полей. Более простой пример сделает это более понятным.

На первом шаге цикла вы получаете одиносимвольную строку «A». Во второй раз VBScript должен перераспределить строку и скопировать два символа («AB») в s. На третьем шаге нужно перераспределить s снова и скопировать три символа в s. На шаге N (26), нужно перераспределить и скопировать N символов в s. Итого — общее количество 1+2+3+. +N, т.е. N*(N+1)/2 копирований.

Если предположить, что в первом примере было 100 записей и 5 полей, то внутренний цикл будут выполнен 100*5 = 500 раз и время, которое потребуется для копирования и перераспределения строк будет пропорционально 500*500 = 250000, что будет довольно много для копирования набора записей скромных размеров.

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

В отдельных случаях преобразования ADO-рекордсета в HTML-таблицу можно попробовать использование GetRows или GetString.

Если вы соединяете строки в JScript, то там строго рекомендуется использование оператора «+=»; т.е. используйте s += «строка», а не s = s + «строка».

Совет 21: Используйте кэширование страниц в браузере и proxy-сервере

По умолчанию в ASP отключено кэширование в веб-браузере и proxy. Смысл этого заключается в том, что ASP-страница — по своей природе динамическая и обычно содержит информацию, которая изменяется со временем. Если ваша страница содержит постоянные данные и не требует регенерации при каждом запросе, то вы должны включить кэширование для браузера и прокси. Это позволит браузерам использовать «кэшируемую» копию страницы в течение некоторого отрезка времени, которым вы можете управлять. Кэширование может значительно снизить нагрузку на вашем сервере.

Какие из динамических страниц могут быть кандидатами на кэширование? Вот некоторые примеры:

  • Страница с прогнозом погоды, где информация обновляется каждые 5 минут.
  • Начальная страница сайта, которая содержит список материалов на сервере или официальные сообщения для печати, которые модифицируются два раза в день.
  • Другие подобные страницы, где обновления происходят раз в несколько часов.

Заметьте, что с кэшированием в браузере или кэшированием proxy, вы получите меньшее количество хитов, зарегистрированных на вашем сервере. Поэтому, если вы хотите точно измерять количество просмотров страниц или количество показов баннеров, то скорее, всего вы не захотите воспользоваться кэшированием.

Кэширование в браузере управляется свойством «Expires» HTTP-запроса, который посылает веб-сервер браузеру. ASP обеспечивает два простых механизма, чтобы установить это свойство. Чтобы заставить страницу «устареть» через несколько минут — установите свойство Response.Expires. Следующий пример сообщает браузеру, что содержание данной страницы истекает через 10 минут:

Установка Response.Expires в отрицательное значение или 0 отключает кэширование. Использование большого отрицательного числа, например -1000 (немного больше, чем 1 день) будет лучше, в силу несоответствий между временем на сервере и в браузере. Второе свойство Response.ExpiresAbsolute позволяет вам устанавливать точное время, в течении которого содержание «устареет»:

Вместо использования объекта Response для того, чтобы установить истечение срока действия страницы, вы можете использовать HTML-тэг . Большинство браузеров «понимают» эту директиву, хотя proxy ее не используют.

Наконец, вы можете указывать является ли содержание допустимым для кэширования HTTP-proxy используя свойство Response.CacheControl. Установив это свойство в значение «Public» вы разрешите proxy кэшировать содержание страницы.

По умолчанию это свойство всегда установлено в «Private». Обратите внимание, что вы не должны разрешать кэширование для proxy страниц, которые показывают данные, специфичные для каждого пользователя, поскольку в этом случае proxy может показывать страницы пользователям с информацией других.

Совет 22: Используйте Server.Transfer вместо Response.Redirect

Метод Response.Redirect сообщает браузеру запросить другую страницу. Этот метод часто используется, чтобы переназначить запрос пользователя, например, к странице идентификации (login) или странице с сообщением об ошибке. Redirect вынуждает сделать новый запрос страницы, результат этого — то, что браузер должен сделать два запроса к веб-серверу и веб-сервер должен обработать дополнительный запрос. В новой версии IIS 5.0 введена новая функция Server.Transfer, которая передает выполнение другой ASP-странице на том же самом сервере. Это помогает избежать дополнительного запроса «браузер-сервер» и в общем и целом приводит к улучшению производительности системы, а также к более короткому времени редиректа и отображения страницы в браузере пользователя.

Следующий скрипт демонстрирует использование Server.Transfer для переназначения запроса в зависимости от значения переменной:

Server.Transfer посылает запрос из одного выполняемого ASP-файла к другому файлу. В течении редиректа выполнение первоначально запрошенного ASP-файла немедленно прекращается без очистки буфера вывода.

Совет 23: Используйте замыкающий слэш в URL каталогов

Этот совет относится не только к ASP-программистам, но и ко всем веб-разработчикам, кто в своей работе создает html-страницы.

Проверьте, всегда ли вы используете замыкающий слэш (trailing slash) — наклонную черту вправо (/) в URL каталогов веб-сайта. Если опустить этот слэш браузер будет делать запрос к серверу, только для того, чтобы сообщить, что он спрашивает о каталоге. Затем браузер будет делать второй запрос, но уже со слэшем на конце URL, и только тогда веб-сервер будет возвращать «главный» (default) документ этого каталога или выдавать список файлов каталога, если в нем нет главного документа и разрешен просмотр каталога. Добавление к URL замыкающего слэша позволяет избежать первого бесполезного запроса к веб-серверу, что, естественно, экономит время, которое требуется для перехода по ссылке. Чтобы подобная ссылка выглядела более приятнее вы можете опустить слэш в названии URL.

Этот совет также относится и к записи ссылок на главную страницу веб-сайта. Используйте

Совет 24: Избегайте использования серверных переменных

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

Также пытайтесь избегать неопределенных вызовов объекта Request (например, Request(«Данные»)). Для элементов, находящихся не в Request.Cookies, Request.Form, Request.QueryString или Request.ClientCertificate, имеется неявный запрос к Request.ServerVariables. Запрос к коллекции Request.ServerVariablesе выполняется намного медленнее, чем доступ к другим коллекциям.

Совет 25: Сделайте upgrade системного программного обеспечения

Системные компоненты постоянно обновляются, поэтому рекомендуется, чтобы вы модернизировали (сделали upgrade) к самой последней версии. Лучше всего установить Windows 2000 (и следовательно, IIS 5.0, ADO 2.5, MSXML 2.5, Internet Explorer 5.0, VBScript 5.1 и JScript 5.1). IIS 5.0 и ADO 2.5 позволяют достичь значительного повышения производительности ваших приложений на мультипроцессорных системах. На серверах под управлением ОС Windows 2000 ASP может респределять нагрузку одновременно на четыре процессора и больше, принимая во внимание, что в предыдущей версии — под IIS 4.0, ASP не делал такого распределения и на два процессора. Насколько много вы используете скриптового кода и ADO в ASP-страницах вашего сайта, настолько больше повышения производительности вы должны увидеть после модернизации к Windows 2000.

Если вы не можете установить Windows 2000 сейчас, вы можете модернизировать ваше системное программное обеспечение к самым последним версиям SQL Server, ADO, VBScript и JScript, MSXML, Internet Explorer и пакета обновления NT 4 (Service Pack). Каждое из перечисленного позволяет улучшить выполнение работы и увеличить надежность.

Asp разработка масштабируемых asp приложений

Данные советы вводят в проблему повышения производительности работы приложений, использующих технологии Microsoft Active Server Pages (ASP) и Visual Basic Scripting Edition (VBScript). Большинство из них были многократно обсуждены и c успехом проверены на практике и будут интересны как новичкам в программировании ASP и VBScript, так и тем, кто уже имеет опыт работы с этими технологиями. При подготовке советов был использованы материалы c веб-сайта корпорации Microsoft Corp. (http://www.microsoft.com) и материалы конференций Relib.com (http://www.relib.com)

Совет 1: Кэшируйте часто используемые данные на сервере

Типичная ASP-страница получает данные из базы данных и затем выводит их в формате HTML. Независимо от скорости работы вашей базы данных, получение данных из памяти сервера будет намного быстрее, чем обработка sql-запроса к конечной базе данных. Получение данных, сохраненных на локальном жестком диске сервера, также обычно быстрее, чем получение информации из БД. Поэтому одним из основных путей увеличения скорости работы вашей ASP-страницы является кэширование часто используемой информации в памяти или на жестком диске.

Кэширование данных — это классический компромисс «место или время». Если вы избрали для кэширования правильный материал, вы можете видеть внушительное повышение производительности вашего приложения. Чтобы кэширование было эффективным нужно использовать для временного хранения только те данные, которые многократно используются для вывода и каждый раз трудоемки для повторных вычислений. Кэш, полный устаревшей информации, будет пустой тратой памяти сервера.

Данные, которые изменяются не часто, будут хорошим кандидатом для кэширования, потому что вам не надо будет волноваться относительно их синхронизации через какое-то время с конечной базой данных. Выпадающие списки (сombo-box), таблицы ссылок, пункты меню, и переменные конфигурации сайта (включая имена DSN, адреса IP и URL) — первые кандидаты для хранения в кэше. Заметьте, что вы можете кэшировать представление данных много быстрее, нежели данные сами себя. Если ASP-страница изменяется не так часто и ее временный кэш будет весьма внушительным (например, полный каталог изделий фирмы), попробуйте использовать сгенерированные HTML-страницы, чем каждый раз загружать сервер генерацией ASP-страниц.

Совет 2: Кэшируйте часто используемые данные в объектах Application или Session

Объекты Application и Session служат для хранения данных в памяти, значения которых могут быть доступны между несколькими HTTP-запросами (в отличие от обычных переменных, чьи значения доступны только в теле одной ASP-страницы). Данные объекта Session доступны только одному пользователю (в течении его сессии), в то время как данные Application доступны всем пользователям веб-сайта. Поэтому часто перед разработчиком возникает вопрос: в каком из объектов сохранять часто используемые данные. Обычно, для инициализации переменных этих объектов используются процедуры файла Global.asa — Application_OnStart() или Session_OnStart() соответственно. Если в вашем Global.asa еще нет этих процедур, то вы можете добавить их сами или инициализировать переменные, когда это будет необходимо. Примером может быть следующая процедура, использующая Application для хранения значений многократно использующейся переменной EmploymentStatusList. Процедура проверяет существование данных в EmploymentStatusList и при необходимости расчитывает их заново:

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

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

Совет 3: Кэшируйте данные на диске веб-сервера

Иногда в памяти вашего веб-сервера может быть слишком большое количество данных. «Слишком много», конечно, является спорным вопросом — это зависит от того, сколько памяти вы хотите использовать, а также число элементов для кэширования и частота, с которой эти элементы будут запрашиваться. В любом случае, если вы имеете слишком большое количество данных для кэширования в памяти, подумайте о переносе кэша в текстовый или XML-файл на жесткий диск веб-сервера. Вы можете одновременно комбинировать кэширование на диске и в памяти, чтобы сформировать оптимальную стратегию для вашего сайта.

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

ASP и COM обеспечивают несколько инструментальных средств для создания схем кэширования на диске. Функции набора записей ADO Save() и Open() сохраняют и загружают recordset c диска. Используя эти методы вы можете переписать код из прошлого совета, заменяя запись в объект Application на метод Save() для записи в файл.

Есть несколько других компонентов, которые работают с файлами:

  • Scripting.FileSystemObject позволяет создавать, читать и записывать файл.
  • MSXML, MicrosoftR XML parser поддерживает сохранение и загрузку XML-документов.
  • Объект LookupTable (например, используемый на MSN.com) — лучший выбор для загрузки простых списков с диска.

Наконец, рассмотрите вопрос принудительного кэширования информации на диске. Сгенерированный HTML-код может быть сохранен на диске как .htm или .asp файл; гиперссылки могут указывать прямо на этот файл. Вы можете автоматизировать процесс генерации HTML, используя коммерческие инструментальные средства типа XBuilder или средства публикации в Интернет, входящие в MicrosoftR SQL ServerT. Кроме того, при помощи директивы #include можно включать отдельные HTML-части в файл ASP или читать HTML-файл с диска используя FileSystemObject. Например, на начальной странице веб-сайта Relib.com (http://www.relib.com/index.asp) приводятся 2 списка последних тем обсуждения двух дискуссионных форумов этого сайта. Отобразить эти списки можно при помощи создания двух наборов записей ADO при каждом обращении к данной странице или, следуя данному совету, сохранить их однажды в виде HTML-файла list.inc, а затем включать в index.asp:

Второй путь работает значительно быстрее.

Совет 4: Избегайте кэшировать медленные компоненты в объектах Application или Session

Несмотря на то, что кэшированиe данных в объектах Application или Session может быть хорошей идеей, кэширование COM-объектов может иметь серьезные ловушки. Занесение наиболее используемых COM-объектов в объекты Application или Session часто соблазняет, но, к сожалению, много COM-объектов, включая все, написанные в Visual Basic 6.0 или ранее, могут вызывать серьезные критические проблемы после сохранения в объектах Application или Session.

В частности, любой компонент, который выполняется медленно, вызовет критические проблемы когда кэшируется в объектах Session или Application. Быстрый (проворный non-agile) компонент — компонент, помеченный ThreadingModel=Both, который объединен Free-threaded marshaler (FTM), или — компонент, помеченный ThreadingModel=Neutral. (Neutral — новая модель в WindowsR 2000 and COM+). Следующие компоненты не проворны:

  • Free-threaded components.
  • Apartment-threaded components.
  • Single-threaded component.
  • Configured components (библиотека Microsoft Transaction Server (MTS)/COM+ и серверные приложения) не проворны пока они Neutral-threaded. Apartment-threaded components и другие не проворные компоненты хорошо работают в пределах страницы (т.е. создаются и разрушаются в пределах одной ASP-страницы).

В IIS 4.0 компонент, отмеченный ThreadingModel=Both выполняется быстро. В IIS 5.0 уже не так достаточно. Компонент не должен только быть отмечен как Both, он должен также объединен FTM.

IIS выполняет проверку компонентов, но если вы хотите ее отменить (т.е. хотите позволить непроворным компонентам быть сохраненными в объектах Application или Session), вы можете установить AspTrackThreadingModel в metabase в значение True. Но это (изменение AspTrackThreadingModel) не рекомендуется.

IIS 5.0 выдаст сообщение об ошибке, если Вы пытаетесь сохранить непроворный компонент, созданный с использованием Server.CreateObject, в объекте Application. Вы можете обойти это, используя в Global.asa, но это также не рекомендуется, поскольку это ведет к проблемам (очереди и сериализация), объясняемым ниже.

Что же все-таки неправильно если вы кэшируете непроворные компоненты? Непроворный компонент, кэшируемый в объекте Session блокирует Session от других рабочих потоков (thread) ASP. ASP обслуживает пул (контейнер) рабочих потоков, запрашиваемых другими сервисами. Обычно, новый запрос обрабатывается первым доступным потоком. Если Session блокирована, то запрос должен ждать поток, когда он станет доступным. Проведем аналогию, которая поможет понять эту ситуацию: вы идете в магазин, выбираете несколько булок, и платите за них в кассе #3. Всякий раз, после того как вы выбрали булки в том магазине, вы всегда оплачиваете их в кассе #3, даже в том случае, когда в других кассах короче очередь или даже вообще нет покупателей.

Сохранение непроворных компонентов в объект Application накладывает столь же негативный эффект на производительность. ASP создает специальный поток для выполнения меделенных компонентов в пределах Application. Это имеет два последствия: все запросы выстраиваются в очередь к этому потоку и все запросы сериализуются. Выстраивание в очередь означает, что параметры были сохранены в общедоступной области памяти; запросы переключаются к специальному потоку; метод компонента выполнен; результаты выстраиваются в общедоступную область. Сериализация (преобразование в последовательную форму) означает, что все методы выполняются в одно время. Для двух различных потоков ASP не возможно одновременное выполнение методов общедоступного компонента. Это уничтожает многопотоковость (параллелизм), особенно на мультипроцессорных системах. Хуже всего то, что все непроворные компоненты в пределах Application совместно используют один поток («Host STA»), так что негативные результаты сериализации налицо.

Смущены? Есть некоторые общие правила. Если Вы пишете объекты в Visual Basic (6.0 или ранее), не храните их в объектах Application или Session. Если вы не знаете потоковую модель объекта, не храните его в кэше. Вместо кэширования где-либо непроворных объектов, вы должны создать и удалить их на каждой странице. Объекты выполнятся непосредственно в рабочем потоке ASP и не будет никакой очереди или сериализации. Производимость будет адекватна, если COM-объекты запущены под IIS и если они не используют много времени, чтобы инициализироваться и уничтожаться. Заметьте, что однопотоковые (single-threaded) объекты не должны использоваться этот путь. Будьте внимательным — VB может создавать однопотоковые объекты! Если вы используете однопотоковые объекты, этот путь (типа таблицы Microsoft Excel) не рассчитывает на высокую производительность.

Наборы записей (recordset) ADO могут безопасно кэшироваться когда ADO отмечен как Free-threaded. Чтобы сделать ADO как Free-threaded используйте файл Makfre15.bat, который обычно зафиксирован в каталоге \\Program Files\Common Files\System\ADO.

Предупреждение: ADO не должен быть Free-threaded, если вы используете Microsoft Access в качестве БД. Набор записей ADO должен быть также вообще отсоединен, если вы не можете управлять конфигурацией ADO на вашем веб-сайте.

Совет 5: Не кэшируйте соединение БД в объектах Application или Session

Кэширование соединений ADO — обычно является плохой стратегией при разработке ASP-сайта. Если один объект Connection сохранен в объекте Application и используется на всех страницах, то все страницы будут бороться за использование этого соединения. Если объект Connection сохранен в ASP-объекте Session, то соединение БД будет создано для каждого пользователя. Это создает излишнюю загрузку веб-сервера и БД.

Вместо кэширования соединений БД, создавайте и уничтожайте объекты ADO на каждой ASP странице, которая использует ADO. Это эффективно, потому что IIS имеет встроенное подключение БД. Более точно, IIS автоматически допускает объединение подключений OLEDB и ODBC. Это гарантирует, что создание и уничтожение связей на каждой странице будут эффективны.

Так как соединенные наборы хранят ссылки на подключение БД, это следует, что вы должны не кэшировать соединенные наборы в объектах Application или Session. Однако, вы можете безопасно кэшировать отсоединенные наборы, которые не держат ссылку на подключение. Чтобы отсоединить набор записей, сделайте следующие два шага:

Совет 6: Разумное использование объекта Session

Теперь, когда в предыдущих советах были раскрыты достоинства кэширования данных в объектах Applications и Sessions, вам предлагается пытаться избегать использования объекта Session. Сессии имеют несколько ловушек когда используются на загруженных сайтах. Под «загруженными» имеются ввиду сайты с сотнями запрашиваемых страниц в секунду или тысячами пользователей одновременно. Этот совет также важен для сайтов, которые должны масштабироваться горизонтально — т.е. те сайты, которые используют несколько серверов для распределения нагрузки и обеспечения отказоустойчивости при сбоях. Для меньших сайтов, типа intranet-сайтов, преимущества применения Sessions все же перевешивают.

Обобщая, ASP автоматически создает Session для каждого пользователя, который обращается к веб-серверу. Каждая сессия занимает приблизительно 10 Кб памяти (сверх любых данных, сохраненных в Session) и немного замедляет выполнение всех запросов. Сессия остается действующей до окончания таймаута (timeout), обычно 20 мин.

Но самая большая проблема при использовании сессий — это не производительность, а расширяемость. Сессии не охватывают все задействованные веб-сервера; как только Session была создана на одном сервере ее данные остаются там. Это означает, что если вы используете сессии на мультисерверном веб-сайте, вы должны придумать стратегию для обработки запросов каждого пользователя, которые должны быть всегда направлены на сервер, на котором существует сессия этого пользователя. Это называется «застреванием» пользователя на сервере (или «липкой сессией»).

Объект Application также не охватывает все сервера: если вам нужно совместно использовать и обновлять данные Application через веб-сервера, вам нужно использовать конечную базу данных. Однако неизменяемые (read-only) данные Application все же полезны на мультисерверных сайтах.

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

Если же вы не используете Session, то убедитесь, что отключили их. Это можно сделать посредством Internet Services Manager (см. документацию по ISM). Но если вам все-таки необходимо использовать сессии, то есть несколько путей уменьшить их удары про производительности.

Вы можете переместить содержимое, которое не требует сессий (например, страницы help и т.д.) в отдельное ASP-приложение, у которого сессии выключены. Кроме того, на страницах, где объект Session не используется, применяйте следующую директиву, помещещаемую вверху страницы:

Одна из основных причин ее применения — то, что Session создает интересную проблему в случае использования фрэймов (frameset). ASP гарантирует, что в любое время будет выполняться только один запрос от Session. Это делается для того, чтобы при одновременном запросе одним пользователем нескольких страниц, только один ASP-запрос был обработан сессией, что помогает избежать проблем многопоточного доступа к объекту Session. К сожалению, в результате этого все страницы в frameset будут загружаться последовательно, а не одновременно, и пользователю придется продолжительное время ждать полной загрузки. Мораль этой истории: если вы не уверены, что с использованием фрэймов и Session ваше приложение правильно работает, то используйте:

Альтернативой использованию объекта Session являются многочисленные параметры управления Session. При передаче малых объемов данных (менее 4 Кб) обычно рекомендуется использовать Cookies, переменные QueryString и скрытые (h >Если в вашем приложении используется много функций VBScript или JScript, то зачастую производительность можно улучшить поместив этот код в откомпилированный COM-объект. Обычно откомпилированная программа выполняется значительно быстрее, чем интерпретируемый код, поэтому откомпилированные COM-объекты будут работать более эффективно, чем вызываемые методы скрипта.

Выделение (инкапсуляция) кода в COM-объект имеет следующие преимущества (не считая производительности):

  • COM-объекты хороши для логического представления структуры приложения.
  • COM-объекты позволяют многократное использование одного кода.
  • Много разработчиков находят код, написанный в VB, C++ или Visual J++ проще в отладке, чем ASP.

Но наряду с, казалось бы, неоспоримыми достоинствами COM-объекты имеют и недостатки, среди которых — время разработки и потребность в различных навыках программирования. Будьте уверены, что инкапсуляция в малых ASP-приложениях может вызвать скорее убытки, чем прибыль. Обычно это случается, когда маленькое количество ASP-кода переносится в объект COM. В этом случае накладные расходы от создания и вызова этого объекта перевешивают выгоду от использования интерпретируемой программы. Определить наиболее выигрышную комбинацию для производительности — использование сценариев ASP или COM-объектов — можно только методом проб и ошибок. Заметим, что Microsoft значительно улучшила ASP-сценарии и производительность ADO в Windows 2000/IIS 5.0 по сравнению с Windows NT 4.0/IIS 4.0. Таким образом, преимущество откомпилированного кода над кодом ASP уменьшилось с введением IIS 5.0 и ваше приложение должно работать быстрее, по сравнению с четвертой версией IIS.

Совет 8: Объявляйте переменные поздно, а удаляйте рано

Данный совет небольшой, но не менее важный в оптимизации ASP, чем все предыдущие. Суть его в следующем: лучше всего объявлять переменные только по мере необходимости и сразу удалять их, как только они становятся ненужными. Это относится и к COM-объектам и к указателям открываемых файлов и другим используемым ресурсам.

Соединения (Connection) ADO и рекордсеты — первостепенные кандидаты для этой оптимизации. Использовав recordset или сonnection для отображения данных сразу же удаляйте эти переменные из памяти, не дожидаясь конца страницы. Не позволяйте рекордсету или соединению остаться незакрытыми.

Например, если вы создаете соединение и открываете набор записей следующим образом:

то закройте их вот так:

Любые другие переменные Microsoft VBScript также лучше устанавливать в Nothing.

Совет 9: Out-of-process как компромисс между производительностью и надежностью

И ASP и MTS/COM+ имеют параметры конфигурации, которые позволяют вам выбрать альтернативу между надежностью и производительностью. Вы должны сделать разумный выбор при разработке ваших ASP-приложений.

Работа ASP-приложений может быть сконфигурирована одним из трех путей. В IIS 5.0 введен термин «уровень изоляции» (isolation level), описывающий эти пути, и который делится на три уровня — Low (низкий), Medium (средний), и High (высокий):

Low Isolation. Поддерживается во всех версиях IIS и самый быстрый. Он выполняет ASP в Inetinfo.exe, который является первичным процессом IIS. Если ASP-приложение дает сбой, то нагрузка ложится на IIS. (Чтобы перезапутить IIS под IIS 4.0 вебмастер должен был вести мониторинг сайта, используя инструменты типа InetMon, и рестартовать его командным файлом, если на сервере произошел сбой. В IIS 5.0 введена более надежная функция рестарта, которая автоматически перезапускает сервер в случае сбоя.)

Medium Isolation. Этот новый уровень, впервые введенный в IIS 5.0, называют out-of-process, т.к. ASP выполняется вне процесса IIS. В Medium Isolation все приложения ASP сконфигурированы для выполнения как среднеразделенный процесс. Это уменьшает число процессов, требуемых для загрузки нескольких ASP-приложений out-of-process. В IIS 5.0 уровень Medium Isolation установлен по-умолчанию.

High Isolation. Поддерживающийся в IIS 4.0 и IIS 5.0 уровень High Isolation также выполняется out-of-process. Если в ASP произошел сбой, то с веб-сервером ничего не случится — ASP-приложение автоматически перезапускается со следующим запросом ASP. В High Isolation, каждое ASP-приложение сконфигурировано для выполнения в собственном участке памяти, что защищает приложения ASP от друг друга (отсюда и название — «высокая изоляция»). Недостаток этого — требование раздельных процессов для каждого ASP-приложения.

Вы спросите, который уровнь лучше? В IIS 4.0 выполнение out-of-process сказывалось довольно негативно на производительности. В IIS 5.0 было проделано много работы для уменьшения последствий от запущенных out-of-process ASP-приложений. Фактически в большинстве испытаний ASP-приложения, запущенные out-of-process под IIS 5.0, выполняются быстрее, чем под IIS 4.0. Независимо от этого, Low Isolation все еще предоставляет лучшую производительность на обеих платформах. Однако, вы не увидите большой выгоды от Low Isolation, если ваш веб-сервер имеет низкую нагрузку. Поэтому, вам не стоит устанавливать этот уровень, до тех пор, пока ваш сервер не будет выполнять запросы в сотни или даже тысячи страниц в секунду. Как всегда, испытание с различными конфигурациями и определяет наиболее лучший выбор.

Заметим, что когда вы выполняете ASP-приложения out-of-process (уровни Medium или High), они выполняются в MTS под NT4 и COM+ под Windows 2000. Т.е. под NT4 они выполняются в Mtx.exe, а под Windows 2000 они выполняются в DllHost.exe. Вы можете увидеть эти процессы запустив Администратор Задач (Task Manager). Вы можете также увидеть как IIS компонует пакеты MTS или приложения COM+ для out-of-process приложений ASP.

Компоненты COM также имеют три параметра конфигурации, хотя они и не полностью аналогичны параметрам настройки ASP. Компоненты COM могут быть: «неконфигурированными» (unconfigured), настроенными как библиотечные или серверные приложения. «Неконфигурированные» — т.е. компонент не зарегистрирован с COM+. Такой компонент будет выполниться в памяти вызывающего процесса, т.е. «in-process» («в процессе»). Библиотечные приложения (Library Applications) также выполняются in-process, но имеют выгоду от сервисов COM+, включая защиту, транзакции и контекстную поддержку. Серверные приложения выполняются в собственной памяти процесса.

Вы сможете увидеть весьма небольшую выгоду неконфигурированных компонентов над библиотечными приложениями. И, вероятно, большую производительность библиотечных приложений над серверными. Это все потому, что библиотечные приложения выполняются в том же самом процессе, что и ASP, в то время как серверные приложения выполняются в их собственном процессе — межпроцессорные запросы более трудоемки, чем работа в in-process (например, при обмене данными recordset между процессами, все данные должны быть скопированы из одного процесса в другой).

Так что же все-таки использовать?

Если вам требуются конфигурации с разумными долями реализации производительности и надежности, то советуем вам следующее: под IIS 4.0 используйте Low Isolation level и MTS Server Packages, под IIS 5.0 используйте Medium Isolation level и COM+ Library Applications. Но учтите, что данный совет — очень общая рекомендация. Например, хостинговые компании обычно устанавливают Medium или High Isolation level, тогда как множество веб-серверов могут работать в Low Isolation. Так что, лучше всего попробовать самому и решить, которая конфигурация непосредственно для вас наилучшим образом выполняет ваши потребности.

Совет 10: Используйте директиву Option Explicit

Используйте директиву Option Explicit в ваших .asp файлах. Расположенная в самом верху .asp файла, она заставляет разработчика объявлять все переменные, которые он использует. Многие программисты считают, что это позволяет быстрее отлаживать приложения, исключая, таким образом, ошибки в написании имен переменных и невнимательное создание новых переменных (например, MyXLMString=. вместо MyXMLString=).

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

Таким образом, использование директивы Option Explicit гарантирует, что все используемые переменные объявлены и доступ к ним будет максимально быстрым.

Совет 11: Используйте локальные переменные в подпрограммах и функциях

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

Совет 12: Копируйте частоиспользуемые данные в переменные

При вызове COM в ASP, вы должны копировать частоиспользуемые данные объекта в переменные ASP-скрипта. Это сократит количество запросов методов COM, которые являются относительно трудоемкими по сравнению с обращением к переменным самого скрипта. При вызове объектов Collection и Dictionary этот совет также сокращает время запросов.

Вообще, если вы пользуетесь объектом данных больше, чем однажды, поместите данные в переменную ASP-скрипта. Главной целью этой оптимизации являются переменные объекта Request (Form и QueryString). Например, на вашем веб-сайте через QueryString передается переменная UserID. Предположите, что этот UserID упомянут дюжину раз на каждой странице. Вместо вызова Request(«UserID») 12 раз, поместите этот UserID в какую-либо переменную наверху ASP страницы и затем используйте эту переменную (а не Request) внутри страницы. Это упразднит 11 COM-запросов!

На практике, доступ к свойствам или методам COM может быть обманчиво дорог. Посмотрите пример, показывающий некоторый обычный код:

Когда этот код выполняется, происходит следущее:

  1. Переменная Foo получена как глобальный объект.
  2. Переменная bar получена как член Foo. Это оказывается запросом COM-метода.
  3. Переменная blah получена как член Foo.bar. Это также оказывается запросом COM-метода.
  4. Переменная qaz получена как член foo.bar.blah. Да, это также оказывается запросом COM-метода.
  5. Вызовите Foo.bar.blah.quaz(1). Еще один запрос COM-метода. Представляете?
  6. Сделайте шаги от 1 до 3 снова, чтобы получить baz. Система не знает, изменил запрос к qaz модель объекта, так что шаги 1 до 3 должны быть выполнены снова, чтобы получить baz.
  7. Получите baz как член Foo.bar.blah.
  8. Сделайте шаги от 1 до 3 снова и получите zaq.
  9. Сделайте шаги от 1 до 3 уже в другой раз и получите abc.

Как видите это ужасно неэффективно (и медленно). Быстрый способ — написать этот код в VBScript: ,pre> Set myobj = Foo.bar.blah ‘Объявляем blah однажды! Myobj.baz = myobj.qaz(1) If Myobj.zaq = Myobj.abc Then ‘.

Если вы используете VBScript 5.0, то можете использовать выражение With:

Совет 13: Избегайте использования переопределяемых массивов

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

Пример ниже показывает использование беспричинного использования Dim и Redim.

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

Совет 14: Используйте буферизацию Response

Вы можете буферизировать целую страницу, включив «response buffering». Это минимизирует количество записей в браузер и, таким образом, улучшит производительность. Каждая запись имеет много непроизводительных издержек (и в самом IIS и в том количестве данных, посланных по проводам), так что меньшее количество записей будет лучше. TCP/IP работает намного более эффективно когда возможно посылать несколько больших блоков данных, чем при пересылке многочисленных маленьких блоков (из-за медленного начала процесса пересылки и сложных алгоритмов проверки).

Есть два пути использования «response buffering». Первый путь — вы можете включить response buffering для приложения, взятого в целом, используя Internet Services Manager. Это рекомендуемый подход, поэтому response buffering включен по-умолчанию для новых ASP-приложений в IIS 4.0 и IIS 5.0. Второй путь — вы можете активировать буферизацию, поместив следующую линию кода вверху ASP-страницы:

Эта линия кода должна быть выполнена прежде, чем любые данные response был записаны в браузер (т.е. прежде, чем появится любой код HTML в ASP-скрипте и прежде, чем были установлены любые Cookies, используя Response.Cookies). Вообще, лучше включить response buffering, как указано в первом случае. Это позволит вам избежать применения вышеупомянутой линии кода в каждой странице.

Есть только одна общая проблема относительно буферизации Response — то, что пользователи чувствуют ASP-страницы менее «отзывчивыми» (даже при том, что время полного получения готовой страницы получается меньше) потому что они должны ждать полную страницу, которая будет произведена прежде, чем, они начинают видеть что-нибудь. Для длинных страниц, вы можете выключить буферизацию, установив Response.Buffer = False. Однако, лучшей стратегией будет использование метода Response.Flush. Этот метод показывает весь HTML, который был записан ASP в браузер. Например, после записи 100 строк из таблицы с 1000-ю записей, ASP может вызывать Response.Flush, чтобы вынудить показать браузер уже готовые 100 строк; это позволяет пользователю увидеть первые 100 строк таблицы прежде, чем остальные строки будут будут получены.

(Заметьте, что в вышеупомянутом примере таблицы с тысячью записей некоторые браузеры не будут отображать таблицу, пока они не получат заключительный HTML-тег

. Так что проверьте ваш браузер на этот счет. Чтобы обойти эту проблему, попробуйте разделить таблицу на несколько более меньших таблиц (с меньшим количеством строк) и вызывать Response.Flush после каждой из них. Новые версии Internet Explorer отображают таблицы прежде, чем они полностью закончены и будут показывать их еще быстрее, если вы определите ширину столбцов таблицы — это поможет избежать расчетов, которые требуются браузеру для самостоятельного вычисления ширины столбцов путем измерения длины строк данных в каждой ячейке таблицы.

Другая обычная проблема с буферизацией Response — то, что она может использовать много серверной памяти при генерации очень больших страниц. Если вам необходимо генерировать такие страницы, то совет будет тем же — попробуйте сочетать буферизацию и Response.Flush.

Совет 15: Группируйте однолинейный код и выражения Response.Write

Однолинейная конструкция VBScript записывает значение «выражения» в исходящий ASP-поток. Если буферизация response не включена (см. Совет 14), то при частом использовании таких выражений, каждое из них приведет к записи данных в браузер путем передачи по сети множества маленьких пакетов, что выполняется медленно. Точно также производительность приложения снижается при частом чередовании маленьких кусочков ASP-кода и HTML. Поэтому данный совет состоит в следующем: замените рядом стоящие однолинейные конструкции одним вызовом Response.Write. Например, в следующем примере отображения таблицы БД показано необоснованно частое переключение в каждой строке между однолинейным кодом VBScript и тэгами HTML:

Ниже приводится более эффективный код, содержащийся в едином блоке VBScript и призванный ускорить отображение данных:

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

Совет 16: Используйте Response.IsClientConnected перед получением больших объемов данных

Если пользователь нетерпелив и торопится, он может отказаться от вашей просмотра ASP-страницы прежде, чем вы начнете выполнять его запрос. Если он нажал в браузере Refresh или ушел на другую страницу вашего сервера, вы получите новый запрос, стоящий в конце очереди ASP-запросов и «отсоединенный» запрос, стоящий в середине очереди. Часто это случается когда ваш сервер сильно загружен (имеет длинную очередь запросов с, соответственно, большим временем ответа) и этот новый запрос делает ситуацию еще хуже. Нет никакого смысла выполнять ASP-скрипт (особенно медленный и тяжеловесный), если пользователь больше не соединен со своим запросом. Вы можете проверить это состояние, используя свойство Response.IsClientConnected. Если оно возвращает False вы должны вызвать Response.End и отказаться от получения остальной части страницы. Фактически, IIS 5.0 использует эту практику — всякий раз, когда ASP собирается выполнять новый запрос, он проверяет, чтобы увидеть как долго запрос был в очереди. Если он был там более, чем 3 секунд, ASP проверит, соединен ли все еще клиент и немедленно закончит запрос, если нет. Вы можете использовать AspQueueConnectionTestTime, чтобы установить этот таймаут в 3 секунды.

Если вы имеете страницу, которая требует очень много времени для выполнения, вы можете проверять Response.IsClientConnected на разных стадиях выполнения. Когда буферизация активирована — хорошая идея также вызывать Response.Flush, чтобы дать понять пользователю, что что-что работает.

Обратите внимание, что в IIS 4.0 Response.IsClientConnected не будет правильно работать, если вы сначала не делаете Response.Write. Если буферизация активирована вы будете также должны делать Response.Flush. На IIS 5.0 нет никакой потребности в этом — Response.IsClientConnected работает прекрасно. В любом случае Response.IsClientConnected требует некоторых затрат времени, поэтому используйте ее только перед действием, которое требует, скажем, по крайней мере, не менее 500 миллисекунд (это большой промежуток времени, если у вас большая нагрузка на сервер). Т.е. вы должны отдавать себе отчет в действиях и не вызывать Response.IsClientConnected перед выводом каждой строки таблицы БД, гораздо лучше будет, если такая проверка будет реже, возможно, перед выводом новых 20-ти или 50-ти строк.

Совет 17: Объявляйте объекты используя тег

Если вам нужно обращаться к объектам, которые затем могут быть не использованы в коде (особенно объекты, содержащиеся в объектах Server или Application), попробуйте объявлять их в global.asa используя следующий синтакс:

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

Совет 18: Используйте объявления TypeLib для ADO и других компонентов

При использовании ADO разработчики часто включают adovbs.txt чтобы получить доступ к различным константам ADO. Этот файл должен быть включен в каждую страницу, в которой нужно использовать эти константы. Но этот файл констант достаточно большой и увеличивает время трансляции каждой ASP-страницы и размер скрипта.

В IIS 5.0 введена способность связать с библиотекой типов компонента, которая позволяет вам один раз сослаться на библиотеку типов и использовать ее на каждой ASP-странице. Причем в каждой странице не надо будет компилировать файл констант и разработчикам компонентов не надо формировать файлы VBScript #include для использования в ASP.

Чтобы обращаться к ADO TypeLib разместите одно из следующих выражений в Global.asa:

Совет 19: Пользуйтесь преимуществами клиентской проверки правильности данных

Современные браузеры имеют широко развитую поддержку XML, DHTML, java-апплетов и Remote Data Service. Пользуйтесь преимуществами этих возможностей всякий раз, когда можете. Все эти технологии помогают сократить на запросах к серверу и обратно, выполняя клиентскую проверку правильности ввода данных (например, проверку, имеет ли кредитная карта правильную контрольную сумму и т.п.). Сократив на обращениях клиент-сервер, вы снимите дополнительную нагрузку с сервера, тем самым — сократите сетевой траффик (хотя начальная страница, посланная браузеру, скорее всего будет большей), а также снизите нагрузку с любых других конечных ресурсов, к которым обращается ваш север (базы данных и пр.). Кроме того, пользователю не надо будет ждать новую страницу с сообщением об ошибке и предложением вернуться назад. Однако все это не означает, что вам надо просто перенести всю вашу проверку с сервера на клиента, нет. Вы должны всегда делать проверку вводимых данных на сервере, потому что она поможет защитить против хакеров или браузеров, которые не поддерживают ваши клиентские процедуры проверки.

Много было сделано для создания HTML, «независимого от браузера». Это часто препятствует разработчику при извлечении выгоды от популярных особенностей браузеров, которые могли бы приносить пользу. Для высокопроизводительных веб-сайтов, которые беспокоятся о «досягаемости» для браузеров, хорошей стратегией будет оптимизация страниц под наиболее популярные программы просмотра. Особенности браузера могут быть легко обнаружены в ASP используя Browser Capabilities Component («компонент возможностей браузера»). Инструментальные средства типа Microsoft FrontPage могут помочь вам при проектировании кода, который будет работать с теми браузерами и версиями HTML, которые вы хотите.

Совет 20: Избегайте конкатенации строк в циклах

Множество программистов делают образование строк в циклах следующим образом:

В таком подходе есть несколько проблем. Во-первых, неоднократная конкатенация (соединение) строк берет квадратичное время или если сказать менее формально, то — время, которое потребуется на выполнение цикла, пропорционально квадрату количества записей к числу полей. Более простой пример сделает это более понятным.

На первом шаге цикла вы получаете одиносимвольную строку «A». Во второй раз VBScript должен перераспределить строку и скопировать два символа («AB») в s. На третьем шаге нужно перераспределить s снова и скопировать три символа в s. На шаге N (26), нужно перераспределить и скопировать N символов в s. Итого — общее количество 1+2+3+. +N, т.е. N*(N+1)/2 копирований.

Если предположить, что в первом примере было 100 записей и 5 полей, то внутренний цикл будут выполнен 100*5 = 500 раз и время, которое потребуется для копирования и перераспределения строк будет пропорционально 500*500 = 250000, что будет довольно много для копирования набора записей скромных размеров.

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

В отдельных случаях преобразования ADO-рекордсета в HTML-таблицу можно попробовать использование GetRows или GetString.

Если вы соединяете строки в JScript, то там строго рекомендуется использование оператора «+=»; т.е. используйте s += «строка», а не s = s + «строка».

Совет 21: Используйте кэширование страниц в браузере и proxy-сервере

По умолчанию в ASP отключено кэширование в веб-браузере и proxy. Смысл этого заключается в том, что ASP-страница — по своей природе динамическая и обычно содержит информацию, которая изменяется со временем. Если ваша страница содержит постоянные данные и не требует регенерации при каждом запросе, то вы должны включить кэширование для браузера и прокси. Это позволит браузерам использовать «кэшируемую» копию страницы в течение некоторого отрезка времени, которым вы можете управлять. Кэширование может значительно снизить нагрузку на вашем сервере.

Какие из динамических страниц могут быть кандидатами на кэширование? Вот некоторые примеры:

  • Страница с прогнозом погоды, где информация обновляется каждые 5 минут.
  • Начальная страница сайта, которая содержит список материалов на сервере или официальные сообщения для печати, которые модифицируются два раза в день.
  • Другие подобные страницы, где обновления происходят раз в несколько часов.

Заметьте, что с кэшированием в браузере или кэшированием proxy, вы получите меньшее количество хитов, зарегистрированных на вашем сервере. Поэтому, если вы хотите точно измерять количество просмотров страниц или количество показов баннеров, то скорее, всего вы не захотите воспользоваться кэшированием.

Кэширование в браузере управляется свойством «Expires» HTTP-запроса, который посылает веб-сервер браузеру. ASP обеспечивает два простых механизма, чтобы установить это свойство. Чтобы заставить страницу «устареть» через несколько минут — установите свойство Response.Expires. Следующий пример сообщает браузеру, что содержание данной страницы истекает через 10 минут:

Установка Response.Expires в отрицательное значение или 0 отключает кэширование. Использование большого отрицательного числа, например -1000 (немного больше, чем 1 день) будет лучше, в силу несоответствий между временем на сервере и в браузере. Второе свойство Response.ExpiresAbsolute позволяет вам устанавливать точное время, в течении которого содержание «устареет»:

Вместо использования объекта Response для того, чтобы установить истечение срока действия страницы, вы можете использовать HTML-тэг . Большинство браузеров «понимают» эту директиву, хотя proxy ее не используют.

Наконец, вы можете указывать является ли содержание допустимым для кэширования HTTP-proxy используя свойство Response.CacheControl. Установив это свойство в значение «Public» вы разрешите proxy кэшировать содержание страницы.

По умолчанию это свойство всегда установлено в «Private». Обратите внимание, что вы не должны разрешать кэширование для proxy страниц, которые показывают данные, специфичные для каждого пользователя, поскольку в этом случае proxy может показывать страницы пользователям с информацией других.

Совет 22: Используйте Server.Transfer вместо Response.Redirect

Метод Response.Redirect сообщает браузеру запросить другую страницу. Этот метод часто используется, чтобы переназначить запрос пользователя, например, к странице идентификации (login) или странице с сообщением об ошибке. Redirect вынуждает сделать новый запрос страницы, результат этого — то, что браузер должен сделать два запроса к веб-серверу и веб-сервер должен обработать дополнительный запрос. В новой версии IIS 5.0 введена новая функция Server.Transfer, которая передает выполнение другой ASP-странице на том же самом сервере. Это помогает избежать дополнительного запроса «браузер-сервер» и в общем и целом приводит к улучшению производительности системы, а также к более короткому времени редиректа и отображения страницы в браузере пользователя.

Следующий скрипт демонстрирует использование Server.Transfer для переназначения запроса в зависимости от значения переменной:

Server.Transfer посылает запрос из одного выполняемого ASP-файла к другому файлу. В течении редиректа выполнение первоначально запрошенного ASP-файла немедленно прекращается без очистки буфера вывода.

Совет 23: Используйте замыкающий слэш в URL каталогов

Этот совет относится не только к ASP-программистам, но и ко всем веб-разработчикам, кто в своей работе создает html-страницы.

Проверьте, всегда ли вы используете замыкающий слэш (trailing slash) — наклонную черту вправо (/) в URL каталогов веб-сайта. Если опустить этот слэш браузер будет делать запрос к серверу, только для того, чтобы сообщить, что он спрашивает о каталоге. Затем браузер будет делать второй запрос, но уже со слэшем на конце URL, и только тогда веб-сервер будет возвращать «главный» (default) документ этого каталога или выдавать список файлов каталога, если в нем нет главного документа и разрешен просмотр каталога. Добавление к URL замыкающего слэша позволяет избежать первого бесполезного запроса к веб-серверу, что, естественно, экономит время, которое требуется для перехода по ссылке. Чтобы подобная ссылка выглядела более приятнее вы можете опустить слэш в названии URL.

Этот совет также относится и к записи ссылок на главную страницу веб-сайта. Используйте

Совет 24: Избегайте использования серверных переменных

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

Также пытайтесь избегать неопределенных вызовов объекта Request (например, Request(«Данные»)). Для элементов, находящихся не в Request.Cookies, Request.Form, Request.QueryString или Request.ClientCertificate, имеется неявный запрос к Request.ServerVariables. Запрос к коллекции Request.ServerVariablesе выполняется намного медленнее, чем доступ к другим коллекциям.

Совет 25: Сделайте upgrade системного программного обеспечения

Системные компоненты постоянно обновляются, поэтому рекомендуется, чтобы вы модернизировали (сделали upgrade) к самой последней версии. Лучше всего установить Windows 2000 (и следовательно, IIS 5.0, ADO 2.5, MSXML 2.5, Internet Explorer 5.0, VBScript 5.1 и JScript 5.1). IIS 5.0 и ADO 2.5 позволяют достичь значительного повышения производительности ваших приложений на мультипроцессорных системах. На серверах под управлением ОС Windows 2000 ASP может респределять нагрузку одновременно на четыре процессора и больше, принимая во внимание, что в предыдущей версии — под IIS 4.0, ASP не делал такого распределения и на два процессора. Насколько много вы используете скриптового кода и ADO в ASP-страницах вашего сайта, настолько больше повышения производительности вы должны увидеть после модернизации к Windows 2000.

Если вы не можете установить Windows 2000 сейчас, вы можете модернизировать ваше системное программное обеспечение к самым последним версиям SQL Server, ADO, VBScript и JScript, MSXML, Internet Explorer и пакета обновления NT 4 (Service Pack). Каждое из перечисленного позволяет улучшить выполнение работы и увеличить надежность.

Илон Маск рекомендует:  Что такое deadlock и как с ним бороться
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL