Почему веб-сайт ASP.net использует высокую загрузку ЦП всего с несколькими посетителями? - PullRequest
0 голосов
/ 10 февраля 2012

Мы работаем над сайтом корзины покупок с более чем 1 лакх продуктами, созданными на основе популярного приложения для электронной коммерции - NopCommerce версии 2.3 (просто для того, чтобы познакомить вас с NopCommerce - это один из лучших и популярных приложений с открытым исходным кодом.коммерческое приложение, построенное на основе ASP.net версии 4 и MVC3.).Сайт был опубликован с двумя языками и единой валютой.

Имея около 80 категорий и 30-40 тыс. Продуктов, он работает довольно хорошо.Я имею в виду не очень плохо.Но это тоже не было хорошо.Как только было добавлено больше продуктов, проблемы с производительностью начинались с таких симптомов, как длительное время отклика (более 40-50 секунд для загрузки) и высокая загрузка ЦП (использование 90-100%) всего с 10-20 пользователями.

Сервер является четырехъядерным процессором Xeon с 16 ГБ ОЗУ - Windows Server 2008 R2 и отлично работает с еще одним веб-сайтом электронной коммерции с 50 тыс. Продуктов на заказном коде разработки, который занимает всего 4–8% ЦП.

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

Позже для исправления проблемы мы профилировали и обнаружили, что это был список в каталоге, который вызывал большую задержку при получении данных из базы данных, что точно нормализовалось.Похоже, что SQL-сервер занимает 80-90% процессорного времени, а w3wp - 30-40% процессорного времени, что постоянно приводит к 100% -ному процессору, и на сайте мало посетителей.Мы посоветовались с несколькими экспертами, они предложили нам хранить ненормализованные данные на диске в двоичном формате, чтобы обойти дорогостоящие соединения с базой данных.Мы провели некоторое исследование и использовали Protobuff для хранения данных нормализованных сериализованных объектов на диске, где хранятся только те поля, которые необходимы для каталога - страница со списком продуктов.Но из-за поддержки некоторых функциональных возможностей спецификации мы создали 3 двоичных файла.Один для объекта продукта, другой для объекта спецификации категории.Эти два файла для каждой категории.И еще один файл для отображения продукта и спецификации - занимает почти 5 МБ.Когда приходят запросы, он читает из сериализованного двоичного файла и возвращает данные объекту.Он считывает файл сопоставления только тогда, когда кто-то фильтрует продукт на основе спецификации.

Так что теперь, когда приходит запрос на страницу со списком продуктов, он проверяет, существует ли двоичный файл, созданный для этой категории, если он не 'Он генерирует хранимую процедуру и сохраняет объект в двоичный файл для последующего использования.Если файл существует, он напрямую читает его из двоичного файла.Благодаря этому мы избежали 90% вызовов БД при загрузке этой страницы.С несколькими пользователями (приложение 30-40) это работает как шарм.И мы можем сократить время отклика до 700-800 мс для каждой загрузки страницы.Это большое улучшение, если мы посмотрим на время загрузки, но процессор все еще находится на более высокой стороне.Разница в том, что теперь w3wp использует 60-70% ЦП при 20-30 посетителях, а sql вряд ли использует 5-8%.

Но с увеличением числа пользователей примерно до 100-120 серверы начинают зависать, а w3wpиспользуя более 100% постоянно.Запросы больше не обрабатываются в секундах, вместо этого загрузка занимает более 20-25 секунд.И тогда большинство запросов никогда не обслуживается.Мы заметили это, когда на сайт приходит несколько запросов.

Мы не являемся экспертами в сериализации и двоичном форматировании.Но мы считаем, что высокая загрузка ЦП обусловлена ​​операцией чтения файла или операцией десериализации, выполняемой при каждой загрузке страницы каталога.

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

В ожидании вашего экспертного заключения по этому поводу.

Заранее спасибо.

Ответы [ 3 ]

1 голос
/ 12 февраля 2012

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

Скажем, у вас есть такой класс:

[Serializable]
public class TestObject : ISerializable {
  public long     id1;
  public long     id2;
  public long     id3;
  public string   s1;
  public string   s2;
  public string   s3;
  public string   s4;
  public DateTime dt1;
  public DateTime dt2;
  public bool     b1;
  public bool     b2;
  public bool     b3;
  public byte     e1;
  public IDictionary<string,object> d1;
}

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

public void GetObjectData (SerializationInfo info, StreamingContext ctxt) {
  SerializationWriter sw = SerializationWriter.GetWriter ();
  sw.Write (id1);
  sw.Write (id2);
  sw.Write (id3);
  sw.Write (s1);
  sw.Write (s2);
  sw.Write (s3);
  sw.Write (s4);
  sw.Write (dt1);
  sw.Write (dt2);
  sw.Write (b1);
  sw.Write (b2);
  sw.Write (b3);
  sw.Write (e1);
  sw.Write<string,object> (d1);
  sw.AddToInfo (info);
}

public TestObject (SerializationInfo info, StreamingContext ctxt) {
  SerializationReader sr = SerializationReader.GetReader (info);
  id1 = sr.ReadInt64 ();
  id2 = sr.ReadInt64 ();
  id3 = sr.ReadInt64 ();
  s1  = sr.ReadString ();
  s2  = sr.ReadString ();
  s3  = sr.ReadString ();
  s4  = sr.ReadString ();
  dt1 = sr.ReadDateTime ();
  dt2 = sr.ReadDateTime ();
  b1  = sr.ReadBoolean ();
  b2  = sr.ReadBoolean ();
  b3  = sr.ReadBoolean ();
  e1  = sr.ReadByte ();
  d1  = sr.ReadDictionary<string,object> ();
}

Это не только сделаетПолезная нагрузка в 10-100 раз меньше, но при этом улучшается производительность в 10 раз, а иногда и в 100 раз.

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

И, наконец, я бы порекомендовал Top 10 ошибок кэширования, которые, как я видел, делают разработчики, особенно при использовании распределенного кэша.

http://www.codeproject.com/Articles/115107/Ten-Caching-Mistakes-that-Break-your-App

0 голосов
/ 22 мая 2013

Ответом на проблемы с базой данных является исправление вашей плохо спроектированной базы данных. «Проблемы» с базами данных не являются фундаментальной проблемой с возможностями баз данных. Это проблема с вашим дизайном.

Исправления бывают разных форм, но это всегда ответ. «Проблемы» с базой данных всегда одинаковы для разных видов проблем.

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

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

0 голосов
/ 10 февраля 2012

Вопрос 1: Что все работает на этом боксе?Если я правильно читаю, у вас есть один сайт с 50 000 товаров (без упоминания о пользователях и посещениях), а другой - с гораздо большим.Когда вы складываете сайты, вы увидите некоторую деградацию, даже если ваш код очень жесткий.

Вопрос 2: У вас есть все слои в одном блоке?Теперь у вас есть конкурирующие проблемы, и вы можете заблокировать некоторые связанные с процессором потоки из-за операций ввода-вывода.

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

Вопрос 4. Профилировали ли вы?Я имею в виду как SQL Server, так и веб-приложение.в противном случае вы не знаете, где может быть проблема, и я сомневаюсь, что кто-то может помочь вам на этом форуме.

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

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

 //let's not focus on the magic string, okay? Think about static
 private static SqlConnection connection = new SqlConnection("{conn string here}");

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

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

...