Как мне добиться лучшей производительности моего сайта? - PullRequest
6 голосов
/ 28 сентября 2011

Хай там!

Я использую IIS7 на сервере Windows 2008.
В разное время мы имеем следующее поведение:

  • Загрузка процессора близка к холостому ходу
  • Запросы помещаются в очередь (отслеживаются с помощью Resource Monitor)
  • Время ожидания превышает 10 секунд

1-4) Пожалуйста, смотрите предыдущие версии и правки

5) Выполнение асинхронных операций

Как и предполагалось, я создал простую сеть ... одну страницу ... с этим кодом:

using System;
using System.Threading;
using System.Web;
using System.Web.UI;

namespace PerformanceTest
{
    public partial class AsyncPage : Page
    {
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            var pageAsyncTask = new PageAsyncTask(this.BeginAsyncOperation, this.EndAsyncOperation, this.TimeoutAsyncOperation, null);
            this.RegisterAsyncTask(pageAsyncTask);
            // or
            //this.AddOnPreRenderCompleteAsync(this.BeginAsyncOperation, this.EndAsyncOperation);

            // this might be useful for doing cleanup or sth alike
            this.PreRenderComplete += HandlePreRenderComplete;
        }

        private void HandlePreRenderComplete(object sender, EventArgs e)
        {
            this.Trace.Write("HandlePreRenderComplete");
            this.Trace.Write(string.Format("managedThreadId #{0}", Thread.CurrentThread.ManagedThreadId));
        }

        private delegate void Sleep(int miliseconds);

        private IAsyncResult BeginAsyncOperation(object sender, EventArgs e, AsyncCallback asyncCallback, object state)
        {
            this.Trace.Write("BeginAsyncOperation");
            this.Trace.Write(string.Format("managedThreadId #{0}", Thread.CurrentThread.ManagedThreadId));

            var sleep = new Sleep(Thread.Sleep);
            return sleep.BeginInvoke(1000, asyncCallback, state);
        }

        private void EndAsyncOperation(IAsyncResult asyncResult)
        {
            this.Trace.Write("EndAsyncOperation");
            this.Trace.Write(string.Format("managedThreadId #{0}", Thread.CurrentThread.ManagedThreadId));
        }

        private void TimeoutAsyncOperation(IAsyncResult asyncResult)
        {
            this.Trace.Write("TimeoutAsyncOperation");
            this.Trace.Write(string.Format("managedThreadId #{0}", Thread.CurrentThread.ManagedThreadId));
        }
    }
}

Кажется, неплохо, не так ли? На самом деле это ничего не меняет, так как в течение более 30 секунд время отклика увеличивается до 8 секунд при использовании ЦП около 0%.

6) Обновлен machine.config

<system.net>
    <connectionManagement>
        <add address="*" maxconnection="12" />
    </connectionManagement>
</system.net>
<system.web>
    <processModel autoConfig="true"
                  maxWorkerThreads="100"
                  maxIoThreads="100"
                  minWorkerThreads="50"
                  minIoThreads="50" />
    <httpRuntime minFreeThreads="88"
                 minLocalRequestFreeThreads="76" />

</system.web>

Ответы [ 4 ]

3 голосов
/ 28 сентября 2011
2 голосов
/ 06 февраля 2012

Вы используете страницу и, возможно, сеанс, поэтому каждая загрузка страницы блокирует все остальные из-за сеанса. ! Таким образом, вы можете назвать это Async или вызвать PageAsyncTask, но страница блокирует все остальные вызовы из-за сеанса, и вызовы страницы попадают в строку для выполнения.

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

Смотрите также: Полная замена сессии ASP.Net

веб-гардер

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

http://msdn.microsoft.com/en-us/library/aa479328.aspx

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

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

В нашем случае проблема была с разгрузкой TCP Chimney в Windows 2008 R2. Windows 2008 старается быть умной, перекладывая работу на сетевую карту, но если сетевая карта достигает максимума, все замедляется, но все нормальные значения производительности показывают небольшую нагрузку.

http://www.iislogs.com/steveschofield/troubleshooting-iis-7-network-performance-issues-and-tcp-chimney-offload-receive-side-scaling-and-network-direct-memory-access

1 голос
/ 28 сентября 2011

Ответ на этот вопрос довольно прост:

Не блокируйте поток

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

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

Делать вещи асинхронно

Переписать ваш код, чтобы он не блокировалнить, вызывая Begin... и End... метод вместо их синхронных братьев и сестер. Async CTP может помочь обернуть эти начальные и конечные вызовы в код, который выглядит синхронно, но выигрыш в производительности выглядит таким огромным, что вам следует подумать о переписывании любого кода, который блокирует страницу дажебез async материала.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...