我们正在开发拥有超过 10 万种产品的购物车网站,该网站基于流行的电子商务应用程序 - NopCommerce 2.3 版(只是为了向您介绍 NopCommerce - 它是最好和流行的开源电子商务应用程序之一建立在 ASP.net 版本 4 和 MVC3 之上。)。该网站以两种语言和单一货币发布。
它拥有大约 80 个类别和 30-40k 产品,效果相当好。我的意思是不是很糟糕。但这也不好。一旦添加了更多产品,性能问题就开始出现,例如响应时间长(加载超过 40-50 秒)和 CPU 使用率高(使用 90-100%),只有 10-20 个用户。
该服务器是配备 16 GB RAM 的四核 Xeon 处理器 - Windows Server 2008 R2,并且可以与另外一个电子商务网站正常工作,该网站有 50k 的定制开发代码产品 - 几乎不占用 4-8% 的 cpu。
我们使用缓存将主页特色产品和类别菜单存储在内存中,以避免数据库调用。它只改进了主页。
后来为了解决问题,我们分析并发现是目录列表导致从数据库中获取数据的延迟很大,这是精细标准化的。SQL 服务器似乎占用了 80-90% 的 CPU,而 w3wp 占用了 30-40% 的 cpu,这一直导致 100% 的 cpu 一直在不断地导致网站上只有少数访问者。我们咨询了一些专家,他们建议我们以二进制格式将非规范化数据存储在磁盘上,以绕过昂贵的数据库连接。我们做了一些研究并使用 Protobuff 将非规范化的序列化对象数据存储到磁盘中,该磁盘仅存储目录 - 产品列表页面所需的那些字段。但是由于维护了一些规范功能,我们过去创建了 3 个二进制文件。一个用于产品对象,另一个用于类别规范对象。这两个文件属于每个类别。还有一个用于产品和规格映射的文件 - 占用将近 5 mb。当请求到来时,它从序列化的二进制文件中读取数据并将数据返回给对象。只有当有人根据规范过滤产品时,它才会读入映射文件。
因此,现在每当对分类产品列表页面的请求时,它会检查是否为该分类创建了二进制文件,如果没有,则使用存储过程生成,并将对象保存为二进制以供以后使用。如果文件存在,则直接从二进制文件中读取。有了这个东西,我们在加载这个页面时避免了 90% 的 db 调用。只有少数用户(大约 30-40 人),它就像一个魅力。我们能够将每个页面加载的响应时间减少到 700-800 毫秒。如果我们查看加载时间,这是一个很大的改进,但 CPU 仍然较高。不同之处在于:现在 w3wp 使用 60-70% 的 cpu 和 20-30 个访问者,而 sql 几乎不使用 5-8%。
但是随着更多用户 appx 达到 100-120,服务器开始挂起,w3wp 的使用率持续超过 100%。请求不再以秒为单位提供服务,而是需要超过 20-25 秒才能加载。然后大多数请求永远不会被满足。当多个请求到达该站点时,我们注意到了这一点。
我们不是序列化和二进制格式器方面的专家。但是我们认为高cpu使用率是由文件读取操作引起的,或者可能是由于在每次目录页面加载时执行的反序列化操作。
我们现在正在寻找解决高 CPU 使用率的可能解决方案。可能是什么问题,我们应该在哪里解决它。您怎么看,是文件读取操作还是反序列化导致了这种情况?我们应该将非规范化对象存储在数据库中吗?我们有什么替代方案来解决这个问题?
等待您的专家意见。
提前致谢。