【问题标题】:How do I achieve a better performance of my website如何获得更好的网站性能
【发布时间】:2011-11-26 16:24:37
【问题描述】:

喂!

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

  • CPU 负载接近空闲
  • 请求排队(由资源监视器监控)
  • 执行时间超过 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 秒,CPU 使用率接近 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>

【问题讨论】:

  • 利用异步将提高性能,因为线程将返回到请求池,并且您将拥有更高程度的并行性。不过,这将意味着严重的重新编程。
  • @MikaelÖstberg 我知道 - 这就是我编辑问题的原因。这只是一个短镜头......当前的峰值可能会变得更糟:(......异步页面将是实现这样一个页面的正确方法,但我不是创造者 - 只是改变者:)

标签: asp.net performance iis-7


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    您使用一个页面,并且可能使用会话,因此每个页面加载都会因为会话而锁定所有其他页面。 !所以你可以叫它Async,或者叫PageAsyncTask,但是页面因为Session而被锁住了所有其他的调用,页面调用被排成一行执行。

    禁用会话只是为了测试,然后如果您不使用任何会话数据,请将此页面禁用。

    另请看:Replacing ASP.Net's session entirely

    网络加德

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

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

    【讨论】:

      【解决方案3】:

      【讨论】:

      • 我使用了一些设置——虽然不是线程。我猜你的问题是“我在哪里可以改变这个”;答案是“在 machine.config 中”。该链接向您显示要更改的设置;我不相信智慧。我希望你能够将 N 移得更高,但进入 N+1 的后果很可能比现在更糟糕......
      【解决方案4】:

      这个问题的答案很简单:

      不要阻塞线程

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

      如果代码阻塞了一个线程几秒钟而实际上没有做任何事情(正如 CPU 使用率所证明的那样),那么有某种 IO 太慢了,显然应该异步进行。如果这些请求不阻塞线程,则 Web 服务器可以处理几乎无限量的并发请求(仅受可用硬件资源的限制)。如果它们阻塞线程,它只能执行与可用线程一样多的请求,这有一个硬性上限。

      异步处理

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

      【讨论】:

      • The fact of the matter is that IIS and an ASP.NET AppDomain is only able to handle N amount of concurrent requests. 在哪里调整这个设置?
      • Rewrite your code so it doesn't lock the thread by invoking Begin... and End... method instead of their synchronous siblings. 这将打开一个新线程来处理任务,不是吗? AppDomain 可以处理多少线程?
      • 感谢您的回答!我想回应:如前所述,我已经使用Thread.Sleep() 调整了我的代码,以确保执行时间为 1 秒(封闭范围)。因此,如果 IIS 可以处理 N 个请求(并处理它们),那么每个被主动处理的请求所花费的时间不应超过 1 秒(加上一些噪音......)。问题是,当执行超过 N 个请求时,它们会排队,并且执行需要 X(排队时间)+ 1 秒。如果我愿意/可以增加并发线程/请求的数量,就不会有问题:)
      • 仅仅增加并发线程的数量只会让你走这么远。真正的问题是每个请求都在等待 IO 时锁定线程。 Begin 不会锁定线程,而是会释放线程,以便其他请求可以使用它,而 End 只会在准备好处理结果所需的纳秒内被调用。
      • 我猜想当你调用Begin... 时,.NET 框架使用了WaitHandle,但这是我不熟悉的实现细节。 :-)
      猜你喜欢
      • 2011-02-07
      • 1970-01-01
      • 2011-11-29
      • 2021-02-05
      • 1970-01-01
      • 2014-10-28
      • 2016-08-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多