Борьба с огромным трафиком - сайт онлайн-билетов

Фон:

Веб-сайт электронной коммерции на базе Asp.net 4.0. Размещено в облаке с выделенным SQL Server 2008 Standard (16 ядер) с 32 ГБ ОЗУ.

Взаимодействие с пользователем:

  1. Пользователи посещают веб-сайт.
  2. просматривать различные категории (пока нет статического контента)
  3. положить товар в корзину
  4. Таймер тикает до 15 минут.
  5. Проверить
  6. Войти/Создать аккаунт
  7. Платеж проходит через шлюз Authorize.Net (пользователь остается на нашем сайте)
  8. Электронные письма отправляются после регистрации/забытого пароля/завершения заказа с использованием стороннего SMTP-провайдера.

Примечание: Наличие билетов проверяется при загрузке страницы товара и при помещении их в корзину. Как только у них есть товар в корзине, таймер наверняка отсчитывает 15 минут. Запрос базы данных каждые 25 секунд для обновления таймера.

Инцидент:

Хорошо, ребята, на прошлой неделе у нас была огромная распродажа, наверное, около 10 000 билетов были выставлены на продажу для фанатов по всей Америке. Мы видели трафик, когда он вышел из-под контроля, и в течение 2-4 часов мы видели, что на нашем сайте было около 1000 одновременных пользователей.

Проблема:

Проблема заключалась в том, что у нас было около 6 облачных серверов по 2 ГБ, которые быстро заполнялись, а затем зависали из-за огромного трафика. Затем нам пришлось раскрутить серверы на 4 Гб, 8 Гб и 16 Гб (по 2 каждый), чтобы справиться с трафиком. во время периода сбоя, который длился около 15-20 минут, веб-сайт перестал отвечать, а также мы увидели, что база данных (выделенная) использует 100% ЦП.

  • gb - объем оперативной памяти серверов.

Каркас:

Код .net написан очень эффективно, он выполняет всего два оператора SQL для получения и построения всех необходимых данных, которые необходимо отобразить в браузере. Вся бизнес-логика, связанная с базой данных, написана в хранимых процедурах. Никаких курсоров, никакого динамического sql в хранимой процедуре.

Необходимые:

  1. Я не могу понять, почему веб-сайт дает сбой... У меня есть множество инструментов анализа кода, которые постоянно сообщают нам, какая часть кода занимает слишком много времени или какой запрос занимает так много времени. Когда у нас большие серверы (8 Гб и более), сайт работает без сбоев.

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

  3. Что если я сохраню страницы в индексе Lucene.Net? а потом рендерить из него? Будет ли ввод-вывод стоить дорого в этом сценарии?

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

Спасибо


person KMX    schedule 14.09.2013    source источник
comment
Каким облачным провайдером вы пользуетесь? Как выглядит ваша инфраструктура? Как вы справляетесь с балансировкой нагрузки? Кроме того, как часто обновляется контент на главной странице? К каким страницам одновременно обращаются пользователи? Это только домашняя страница или есть какие-то популярные страницы?   -  person Maz    schedule 15.09.2013
comment
@Maz, стеллажное пространство, межсетевой экран с подключением к стойке, f5 LB, контент обновляется только тогда, когда у нас есть новый продукт в продаже, никаких изменений во время продажи. перечислены только продукты. все продукты популярны, клиенты в основном заинтересованы в нескольких продуктах. Категории › товары › добавить в корзину › оформить › войти › оплатить › получать уведомления по электронной почте. Мы используем стороннего поставщика услуг электронной почты), обработка запасов в режиме реального времени, поэтому мы видим, как продаются билеты, при бронировании (в корзине/ожидающих оплаты) и как они доступны) утилита запасов запускается каждые 10 секунд для очистки. Таймер на тележке работает в течение 15 минут, чтобы дать достаточно времени для завершения.   -  person KMX    schedule 15.09.2013
comment
Вашим первым шагом, вероятно, будет кеширование запросов. Я рекомендую использовать memcached ( memcached.org). Memcached — это хранилище ключей и значений в памяти. Идея использования memcached заключается в том, чтобы превратить процессы запросов в en.wikipedia.org/wiki/Memcached#. Example_code Это только первый шаг, и он может решить ваши проблемы, а может и нет. Одна из проблем, с которой вы можете столкнуться при работе с memcached, — это проблема толпы, набрасывающейся на code.google. com/p/memcached/wiki/   -  person Maz    schedule 15.09.2013


Ответы (2)


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

Для этого вам не нужно преобразовывать продукты в html или какой-либо сторонний код. Asp.NET имеет встроенную поддержку выходного кеша.

Веб-формы:

<%@ OutputCache Duration="60" VaryByParam="none" %>

МВК:

[OutputCache(Duration=60, VaryByParam="none")]
public ActionResult Index()
{
    return View();
}

Где Duration — это продолжительность кэширования страницы в секундах, а VaryByParam — параметр URL-адреса, который действует как ключ для этой страницы. Он будет кэшировать страницу для каждого предоставленного параметра, поэтому обычно вы не оставляете ничего для индекса и ProductId для конкретной страницы продукта)

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

person Ortiga    schedule 14.09.2013
comment
так будет ли это работать для вложенных элементов управления, которые динамически загружаются во время выполнения всего веб-приложения? - person KMX; 15.09.2013
comment
Не совсем уверен, что правильно понял ваш вопрос. Но, насколько мне известно, кешируется только окончательный вывод html. Так что да, он будет кэшировать каждый элемент управления, добавленный на страницу. - person Ortiga; 15.09.2013

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

Lucene.NET может помочь, только если вы используете полнотекстовые индексы sql, и в этом случае было показано, что он более эффективен. Но только в том случае, если поиск является вашим узким местом.

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

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

person Mark J Miller    schedule 16.09.2013
comment
Ну и наличие билетов проверяется при загрузке страницы товара и когда они кладутся в корзину. Как только у них есть товар в корзине, таймер наверняка отсчитывает 15 минут. Запрос базы данных каждые 25 секунд для обновления таймера. - person KMX; 17.09.2013
comment
Ну, мы не используем никакого поиска. Он никогда не нужен. Посетители приходят, они знают свои целевые продукты, они посещают эти категории, выбирают свои продукты и покупают. Я упомянул об использовании lucene для того, чтобы сохранить попадание из базы данных ради рендеринга информации о продукте, так как она будет исходить из lucene, а поиск будет выполняться внутри кода. Товаров около 20-30. поэтому размер индекса будет очень маленьким. - person KMX; 17.09.2013