Всем привет!
Мы разрабатываем веб-портал для внутрикорпоративного и внешнего использования. В качестве среды разработки был выбран по ряду причин ASP.NET 2, но в текущей ситуации, которую опишу чуть позже, возникает все больше и больше вопросов по целесообразности его применения.
Предисловие.
Черновой вариант портала с базовой функциональностью был разработан за 2 месяца. Используемые технологии: web-parts, client callbacks, themes, и все остальные примочки, предоставляемые ASP.NET. Т.е. мы постарались взять максимум возможностей, которые есть в этой платформе, и применить их с максимальной эффективностью. Пока шла разработка и тестирование внутри локальной сети, все было хорошо. Однако в один прекрасный момент было принято решение опубликовать сайт в интернете для его тестирования сторонними пользователями. И тут же посыпались жалобы о громадном потребляемом трафике. И началась наша борьба с монстром, известным как пожиратель трафика.
Борьба с врагом.
Итак, было две причины, по которым шел огромный расход трафика.
Callback-посты, которые происходили довольно часто (у нас на портале есть чат), и которые были довольно-таки большими.
Сами страницы были очень объемны.
Первое, что сразу бросилось в глаза — это, конечно, VIEWSTATE. Это скрытое поле занимало львиную долю трафика. Сразу начались эксперименты с EnableViewState. Ни к чему хорошему они не привели, т.к. использовалось много обработчиков, которые косвенно завязаны на ViewState, например, DropDownList.OnSelectedIndexChanged. В конце концов, остановились на хранении ViewState-а на сервере:
protected override PageStatePersister PageStatePersister {
get { return new SessionPageStatePersister(Page); }
}
Однако и после этого оказалось, что поле VIEWSTATE осталось, и все-равно использует много трафика. Начали его декодировать, и обнаружилось, что в нем еще хранятся две большие порции данных: ControlState и ControlsRequiresPostBack. Если с первым еще более или менее понятно, то второе вызвало недоумение. Поковырявшись с рефлектором, обнаружилось, что ImageButton-ы (которых у нас было достаточно много) требовали специальное поле, которое и записывалось в конечном счете во VIEWSTATE. Это касается и некоторых других контролов, но суть не в этом. Заменив ImageButton-ы на обычные LinkButton с картинками внутри, проблема ушла. Обычный Callback-пост снизился в общем счете до пары килобайт, что стало более или менее приемлимо.
Покончив с постами, мы взялись уже за сами страницы. Итак, было принято решение бороться в двух направлениях:
Убирание мусора.
Сжатие трафика.
Под мусором подразумевается всяческого рода пробелы и табуляции, которые никоим образом не нужны для рендеринга HTML, но которые удобны разработчикам для читабельности кода. Т.к. все наши страницы соответствуют стандартам XHTML 1.1, то показалось самым обычным загрузить текст в XmlDocument и переформатировать его с опцией PreserveWhitespace, равной false. Затея, конечно, не удалась, т.к. всякого рода " " не соответствуют спецификации XML, а добавление ENTITY в DOCTYPE приводит к не совсем корректному отображению страниц (не смогу сказать, почему, вопрос к разработчикам браузеров). Остался последний вариант — обрабатывать текст
регулярными выражениями, что и было успешно осуществлено.
По вышеприведенной ссылке можно обнаружить и ссылку на
модуль компрессии, который также был успешно внедрен.
Партизанская война ASP.NET с пользователями.
Итак, вроде бы враг побежден!? Проверка сниффером показала, что вроде бы все хорошо, наконец-то объем страниц с сотни килобайт снизился до 20-30, что еще как-то приемлимо. Замечу, что полезного текста на странице всего килобайт 5, остальное занимают теги (примерно 30 кб), скрипты (еще 30 кб) и по мелочи: стили (из-за тем) — 8кб и идентификаторы — 5 кб. Конечно, использование CssClass и кратких идентификаторов как-то спасает ситуацию, но это капля в море.
Но война еще не окончена. Сниффер показал, что помимо самих страниц идет подгрузка скриптов с урлом "WebResource.axd?параметры". Любое изменение этого потока (компрессия или убирание мусора) тут же его ломает, и скрипты вообще не подгружаются. Попробовав несколько методов, включая всяческого рода грязные хаки, мы пришли к выводу, что от него избавиться честным способом не получится, кроме того, чтобы не использовать callback-и, веб-парты и всякого рода другие приятные мелочи, но которые требуют подгрузки скриптов и картинок из System.Web.dll. А ведь этот довесок всегда грузится при обновлении страниц, и его размер колеблется от 20 до 30 килобайт, причем он не кэшируется (опера вроде кэширует что-то, но в основном пользователи-то под ней не сидят).
И к чему мы пришли? Для снижения нагрузки на трафик и сервер, необходимо:
Не использовать встроенные серверные контролы. Они добавляют ViewState и тащат за собой скрипты из System.Web.dll.
Не использовать встроенные callback-и. Они делают довольно-таки значительный POST-запрос, плюс к тому же требуют подгрузки скриптов из System.Web.dll.
Не использовать WebPart-ы. Они создают большие таблицы, стили, также тащат скрипты, и вообще работают не особо хорошо (почему бы сворачивание не сделать чисто на клиентской стороне, а для сохранения настройки сделать callback?).
В итоге, так и навязывается вопрос — а пригоден ли ASP.NET для создания интернет-сайтов? Встроенные механизмы Session, MemberShip не так уж сложно пишутся на других средах, хоть на том же перле или пхп, а проблем (см. выше) ASP.NET создает выше крыши. Повторюсь, — я не говорю про внутрикорпоративное использование, где совершенно другие критерии для оценки веб-приложений. По недавним исследованиям, для большинства пользователей скорость загрузки страниц критична — и они не хотят долго ждать пока откроется страница, и уж тем более платить за лишний трафик. Вот и возникают такие вот вопросы
... << RSDN@Home 1.2.0 alpha rev. 667>>
10.12.06 15:35: Перенесено модератором из 'Компьютерные священные войны'. Технические вопросы лучше обсудить в тематическом форуме. — Хитрик Денис