如何实现更好的网站性能

时间:2021-11-18 08:09:07

Hy there!

I'm running IIS7 on a Windows 2008 server.
On peek times we have following behaviour:

我在Windows 2008服务器上运行IIS7。在偷看时间,我们有以下行为:

  • CPU load is near idle
  • CPU负载接近空闲

  • Requests get queued (monitored with Resource Monitor)
  • 请求排队(使用资源监视器监视)

  • Exeuction time gets over 10sec
  • 执行时间超过10秒

1-4) Please see previous versions and edits

1-4)请参阅以前的版本和编辑

5) Doing stuff async

5)做东西异步

As suggested, I've created a simple web ... one page ... with this codebehind:

正如所建议的那样,我创建了一个简单的网页......一个页面......这个代码隐藏:

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));
        }
    }
}

Seems quite good, doesn't it? Actually it changes nothing, as stressing for more than 30 seconds, response time goes up to 8 seconds with CPU usage near 0%.

看起来挺好的,不是吗?实际上它没有任何变化,因为压力超过30秒,响应时间上升到8秒,CPU使用率接近0%。

6) Updated machine.config

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 个解决方案

#2


2  

You use a Page, and probably Session, so every page load lock all the other because of the Session. ! So you may call it Async, or call the PageAsyncTask, but the page is lock all the other calls because of the Session, and the page calls are get in a line to execute.

您使用Page,可能还有Session,因此每个页面都会因为Session而加载所有其他页面。 !因此,您可以将其称为Async,或调用PageAsyncTask,但由于Session,页面将锁定所有其他调用,并且页面调用将在一行中执行。

Disable the Session just for test, and then if you not use any session data, keep it disable for this page.

禁用会话仅用于测试,如果您不使用任何会话数据,请对此页面禁用它。

Look also: Replacing ASP.Net's session entirely

另外:完全替换ASP.Net的会话

Web Garder

You can setup a web garden, that is give more pools to the same web application. By do that you need to re-check all your code and include synchronization with mutex, or database lock, because with two or more pools the same data can be access and write by different threads.

您可以设置Web园,即为同一Web应用程序提供更多池。通过这样做,您需要重新检查所有代码并包含与互斥锁或数据库锁的同步,因为有两个或更多池,相同的数据可以由不同的线程访问和写入。

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

#3


1  

The answer to this is quite easy:

答案很简单:

Don't block the thread

The fact of the matter is that IIS and an ASP.NET AppDomain is only able to handle N amount of concurrent requests. You can increase this number, but having a complete lock on thousands of concurrently running threads is a bottleneck nightmare. Without knowing exactly what's causing the ASP.NET page to respond in less than one second it's hard to suggest any performance tweaks, but the problem here is probably not with IIS, but in the code.

事实上,IIS和ASP.NET AppDomain只能处理N个并发请求。您可以增加此数量,但对数千个并发运行的线程进行完全锁定是一个瓶颈噩梦。如果不知道是什么原因导致ASP.NET页面在不到一秒的时间内响应,就很难建议任何性能调整,但这里的问题可能不是IIS,而是代码中。

If the code is blocking a thread for several seconds without actually doing anything (as the CPU usage is witness to), there is some kind of IO that is so slow it should obviously be made asynchronously. A web-server can server an almost infinite amount of concurrent requests (only limited by available hardware resources) if these requests don't block threads. If they block threads, it can only perform as many requests as there are available threads, which has a hard upper limit.

如果代码在没有实际执行任何操作的情况下阻塞线程几秒钟(因为CPU使用情况见证了),那么某种类型的IO很慢,显然应该是异步的。如果这些请求不阻止线程,则Web服务器可以服务几乎无限量的并发请求(仅受可用硬件资源限制)。如果它们阻塞线程,它只能执行与可用线程一样多的请求,这些线程有一个硬上限。

Do stuff asynchronously

Rewrite your code so it doesn't lock the thread by invoking Begin... and End... method instead of their synchronous siblings. The Async CTP can help with wrapping these Begin and End calls in code that looks synchronous, but the performance benefit here looks to be so huge that you should consider rewriting whatever code it is that is locking up the page even without the async stuff.

重写您的代码,以便它不会通过调用Begin ...和End ...方法而不是它们的同步兄弟来锁定线程。 Async CTP可以帮助将这些Begin和End调用包装在看起来同步的代码中,但是这里的性能优势看起来非常巨大,以至于您应该考虑重写任何代码即使没有异步内容也会锁定页面。

#4


1  

We had a similar problem once. It turned out that it was not our code that was causing the problem.

我们曾经遇到过类似的问题。原来,我们的代码不是造成问题的原因。

In our case the problem was with the TCP Chimney offload in windows 2008 R2. Windows 2008 trys to be clever by offloading work to the network card, but if the network card gets maxed out things slow down, but all the normal performance values show little load.

在我们的例子中,问题在于Windows 2008 R2中的TCP Chimney卸载。 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


#2


2  

You use a Page, and probably Session, so every page load lock all the other because of the Session. ! So you may call it Async, or call the PageAsyncTask, but the page is lock all the other calls because of the Session, and the page calls are get in a line to execute.

您使用Page,可能还有Session,因此每个页面都会因为Session而加载所有其他页面。 !因此,您可以将其称为Async,或调用PageAsyncTask,但由于Session,页面将锁定所有其他调用,并且页面调用将在一行中执行。

Disable the Session just for test, and then if you not use any session data, keep it disable for this page.

禁用会话仅用于测试,如果您不使用任何会话数据,请对此页面禁用它。

Look also: Replacing ASP.Net's session entirely

另外:完全替换ASP.Net的会话

Web Garder

You can setup a web garden, that is give more pools to the same web application. By do that you need to re-check all your code and include synchronization with mutex, or database lock, because with two or more pools the same data can be access and write by different threads.

您可以设置Web园,即为同一Web应用程序提供更多池。通过这样做,您需要重新检查所有代码并包含与互斥锁或数据库锁的同步,因为有两个或更多池,相同的数据可以由不同的线程访问和写入。

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

#3


1  

The answer to this is quite easy:

答案很简单:

Don't block the thread

The fact of the matter is that IIS and an ASP.NET AppDomain is only able to handle N amount of concurrent requests. You can increase this number, but having a complete lock on thousands of concurrently running threads is a bottleneck nightmare. Without knowing exactly what's causing the ASP.NET page to respond in less than one second it's hard to suggest any performance tweaks, but the problem here is probably not with IIS, but in the code.

事实上,IIS和ASP.NET AppDomain只能处理N个并发请求。您可以增加此数量,但对数千个并发运行的线程进行完全锁定是一个瓶颈噩梦。如果不知道是什么原因导致ASP.NET页面在不到一秒的时间内响应,就很难建议任何性能调整,但这里的问题可能不是IIS,而是代码中。

If the code is blocking a thread for several seconds without actually doing anything (as the CPU usage is witness to), there is some kind of IO that is so slow it should obviously be made asynchronously. A web-server can server an almost infinite amount of concurrent requests (only limited by available hardware resources) if these requests don't block threads. If they block threads, it can only perform as many requests as there are available threads, which has a hard upper limit.

如果代码在没有实际执行任何操作的情况下阻塞线程几秒钟(因为CPU使用情况见证了),那么某种类型的IO很慢,显然应该是异步的。如果这些请求不阻止线程,则Web服务器可以服务几乎无限量的并发请求(仅受可用硬件资源限制)。如果它们阻塞线程,它只能执行与可用线程一样多的请求,这些线程有一个硬上限。

Do stuff asynchronously

Rewrite your code so it doesn't lock the thread by invoking Begin... and End... method instead of their synchronous siblings. The Async CTP can help with wrapping these Begin and End calls in code that looks synchronous, but the performance benefit here looks to be so huge that you should consider rewriting whatever code it is that is locking up the page even without the async stuff.

重写您的代码,以便它不会通过调用Begin ...和End ...方法而不是它们的同步兄弟来锁定线程。 Async CTP可以帮助将这些Begin和End调用包装在看起来同步的代码中,但是这里的性能优势看起来非常巨大,以至于您应该考虑重写任何代码即使没有异步内容也会锁定页面。

#4


1  

We had a similar problem once. It turned out that it was not our code that was causing the problem.

我们曾经遇到过类似的问题。原来,我们的代码不是造成问题的原因。

In our case the problem was with the TCP Chimney offload in windows 2008 R2. Windows 2008 trys to be clever by offloading work to the network card, but if the network card gets maxed out things slow down, but all the normal performance values show little load.

在我们的例子中,问题在于Windows 2008 R2中的TCP Chimney卸载。 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