Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么ASP.net网站只需要很少的访问者就可以使用高CPU?_Asp.net_Performance_Serialization_Shopping Cart_Nopcommerce - Fatal编程技术网

为什么ASP.net网站只需要很少的访问者就可以使用高CPU?

为什么ASP.net网站只需要很少的访问者就可以使用高CPU?,asp.net,performance,serialization,shopping-cart,nopcommerce,Asp.net,Performance,Serialization,Shopping Cart,Nopcommerce,我们正在开发购物车网站,拥有超过10万种产品,是在流行的电子商务应用程序NopCommerce版本2.3的基础上开发的(只是为了向您介绍NopCommerce,它是在ASP.net版本4和MVC3的基础上开发的最受欢迎的开源电子商务应用程序之一)。该网站以两种语言和单一货币发布 大约有80个类别和30-40k个产品,它工作得相当好。我的意思是不太坏。但也不好。一旦添加了更多产品,性能问题就开始出现,表现为响应时间长(加载时间超过40-50秒)和CPU使用率高(利用率90-100%),只有10-2

我们正在开发购物车网站,拥有超过10万种产品,是在流行的电子商务应用程序NopCommerce版本2.3的基础上开发的(只是为了向您介绍NopCommerce,它是在ASP.net版本4和MVC3的基础上开发的最受欢迎的开源电子商务应用程序之一)。该网站以两种语言和单一货币发布

大约有80个类别和30-40k个产品,它工作得相当好。我的意思是不太坏。但也不好。一旦添加了更多产品,性能问题就开始出现,表现为响应时间长(加载时间超过40-50秒)和CPU使用率高(利用率90-100%),只有10-20个用户

该服务器是四核Xeon处理器,内存为16 GB—Windows server 2008 R2,并且与另一个电子商务网站配合良好,在定制开发代码上有50k产品—几乎占用4-8%的cpu

我们使用缓存将主页特色产品和分类菜单存储在内存中,以避免数据库调用。它只改进了主页

后来为了解决这个问题,我们分析并发现是目录列表导致了从数据库中获取数据的大量延迟,这是经过精细规范化的。SQL server似乎占用了80-90%的CPU,而w3wp占用了30-40%的CPU,这导致网站始终保持100%的CPU,只有很少的访问者。我们咨询了几位专家,他们建议我们以二进制格式将非规范化数据存储在磁盘上,以绕过昂贵的数据库连接。我们做了一些研究,并使用Protobuff将非规范化的序列化对象数据存储到磁盘,磁盘只存储目录-产品列表页面所需的字段。但由于维护了一些规范功能,我们用来创建3个二进制文件。一个用于产品对象,另一个用于类别规范对象。这两个文件按类别列出。另外还有一个用于产品和规范映射的文件—占用了近5 mb的空间。当请求到来时,它读取序列化的二进制文件并将数据返回给对象。只有当有人根据规范过滤产品时,它才会读入映射文件

所以现在,每当出现分类产品列表页面的请求时,它都会检查是否有为该类别创建的二进制文件,如果没有,它会使用存储过程生成,并将对象保存为二进制文件以供以后使用。若文件存在,它直接从二进制文件中读取。通过这种方式,我们在加载此页面时避免了90%的db调用。只有很少的用户(appx.30-40),它就像一个魅力。我们能够将每个页面加载的响应时间减少到700-800毫秒。这是一个很大的改进,如果我们看看加载时间,但CPU仍然在较高的一面。不同之处在于:现在w3wp使用60-70%的cpu和20-30个访问者,而sql几乎不使用5-8%

但随着appx到100-120的用户越来越多,服务器开始挂起,w3wp的使用率不断超过100%。请求不再在几秒钟内送达,而是需要20-25秒才能加载。然后,大多数请求从未得到满足。当多个请求到达站点时,我们注意到了这一点

我们不擅长序列化和二进制格式化程序。但是我们认为cpu的高使用率是由文件读取操作引起的,或者可能是由于在每个目录页加载上执行的反序列化操作

我们现在正在寻找解决高CPU使用率的可能解决方案。问题可能是什么,我们应该在哪里解决它。您认为是文件读取操作还是反序列化导致了这种情况?我们应该将非规范化对象存储在db中吗?我们有什么办法来解决这个问题

等待您的专家意见


提前谢谢。

问题1:这个盒子上运行的是什么?如果我读对了,你有一个网站有50000个产品(没有提到用户或点击率),另一个网站有更多。当您堆叠站点时,您将看到一些降级,即使您的代码非常紧凑

问题2:在一个盒子上有所有层吗?您现在有了相互竞争的问题,并且可能会由于I/O操作而阻塞一些CPU绑定的线程

问题3:您是否对代码进行了审查,以确保正确的开发概念和方法(SOLID等)?否则,您可能会占用资源超过需要的时间,并导致问题

问题4:你介绍过吗?我指的是SQL Server和web应用程序。如果没有,你不知道问题可能在哪里,我怀疑在这个论坛上是否有人能帮助你

即使有数以百万计的“产品”,一个正确设计的数据库和网站也应该相当快。但是,不同的因素组合在一起代表性能。所有层上的所有部分都会影响应用程序

举个例子,我曾经咨询过一家公司,该公司开发了一款即将消亡的高性能电子商务应用程序。在代码评审中,所有的部分似乎都很好。在测试中,页面和数据库都运行良好。但他们从未强调过这一制度。如果他们有,他们会抓到这一点疯狂

 //let's not focus on the magic string, okay? Think about static
 private static SqlConnection connection = new SqlConnection("{conn string here}");
整个站点都在通过一个SQL连接进行过滤,因为一个开发人员不理解底层连接池的概念,并且认为对象初始化比通过静态“始终打开”连接进行过滤更容易成功


在您分析应用程序之前,这里没有可以回答的问题。一旦你发现一个问题并提出问题,有人会站出来说“这就是你解决问题的方法”。您可以在此问题中添加更多信息,但在确定问题而不是一般症状之前,您将一事无成。

由于您有CPU问题,我怀疑反序列化是主要原因。在这种情况下,通过自己实现
ISerializable
接口,可以使序列化、反序列化速度提高近100倍。我以前用过这种技术
[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;
}
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> ();
}