65.9K
CodeProject 正在变化。 阅读更多。
Home

提升 Dotnetnuke 框架性能

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (1投票)

2014年10月2日

CPOL

4分钟阅读

viewsIcon

16001

如何分析和优化您的 dotnetnuke 网站以获得最佳性能。

引言

我多年来一直使用 Dotnetnuke 框架(版本 6.0)开发在线学习解决方案。最近,我面临了一个巨大的挑战,那就是:允许 10,000 名并发用户同时使用该系统(参加测验、学习等)。

为了实现这样的性能,我不得不深入研究 Dotnetnuke。以下是我的建议:

技巧

1. 减少 HTTP 请求次数

默认情况下,DNN 会自动包含许多样式表文件:default.css, portals.css, skin.css, ie.css 等。这很方便,但却要付出代价!所以我的解决方案是将所有这些文件合并为一个,进行最小化处理,然后放在静态服务器上。

只需在 Default.aspx.cs 文件中注释掉以下几行代码即可实现此功能。

//ClientResourceManager.RegisterDefaultStylesheet(this, Globals.HostPath + "default.css");
//ClientResourceManager.RegisterIEStylesheet(this, Globals.HostPath + "ie.css");
//ClientResourceManager.RegisterStyleSheet(this, ctlSkin.SkinPath + "skin.css", FileOrder.Css.SkinCss);
//ClientResourceManager.RegisterStyleSheet(this, ctlSkin.SkinSrc.Replace(".ascx", ".css"), FileOrder.Css.SpecificSkinCss);

然后将合并后的样式表放在 Default.aspx 文件的顶部。

2. 减少 DOM 元素的数量

众所周知,80% 的最终用户响应时间花在前端,所以请尽可能地最小化您的 DOM 元素。

在 DNN(6.0 或更高版本)中,模块是通过 DIV 结构(大约 4 个嵌套的 DIV)注入到皮肤中的,以确保布局处于正确的状态。在包含许多模块的页面中,会生成大量冗余的 DIV

我的建议是尽可能地将用户控件直接放在皮肤中。

例如:与其创建一个“菜单模块”并将其注入到 HeaderPane,我只是声明 usercontrol

<%@ Register TagPrefix="ctl" TagName="MENU" Src="~/DesktopModules/YourPath/Menu.ascx" %>

然后,像这样直接将其放在皮肤中

<div class="wrapper">
    <ctl:MENU ID="ctlMenu" runat="server"></ctl:MENU>
    <div class="clear"></div>
    <div class="container-fluid">

    ...

此外,上述“经典样式”可以减少数据库命中次数,因为无需从数据库加载模块。

请记住

  • 将页面上的 DNN 模块数量保持在最低限度。
  • 不要在前台使用 Rad 控件,如 RadTreeview(它会产生大量的 DOM)- 这只是我的观察。

3. 将组件拆分到无 Cookie 的域上

将您的所有 CSS、JS、字体、Flash、图片等文件放在几个无 Cookie 的域上(2-4 个域以减少 DNS 查找)。考虑使用 CDN 来更有效地向用户提供内容。

4. 使用 Gzip 压缩

请务必使用 Gzip 压缩。在 DNN 6.0 及更高版本中,Gzip 功能被省略了,因此请改用 IIS 压缩。

这里是一个实现此目标的绝佳链接。

5. 分离用户数据和源代码

~/Portals/0”是大多数开发人员存放用户数据(图片、视频、Flash 等)的地方。

不要这样做。这会使您以后难以维护,并且您无法从使用静态域或 CDN 网络中获益。

尝试通过使用虚拟目录(指向不同的 SAN 位置)来分离您的用户数据,然后您就可以在该数据上部署任何您想要的东西(无 Cookie 域、跨分布式服务器同步等)。

Simpy use Server.MapPath("/DATA") to get the desired path.

Rad 控件自 2009 年起就已集成到 DNN 中,开发人员通常通过 DNN 包装器来使用这些控件。

这些 DNN Rad 控件不理解虚拟路径,我必须让它们理解。以下是 RadEditor 的解决方案:

1. 注册 Rad 控件
<%@ Register TagPrefix="telerik" 
Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %>

声明

<telerik:RadEditor id="radContent" 
Width="100%" runat="server" Height="500px"></telerik:RadEditor>
2. 在 web.config 中注册处理程序

<system.webServer> 部分的 <handlers> 下,为 RadEditor 注册 DialogHandler

<add name="Telerik.Web.UI.DialogHandler" path="Telerik.Web.UI.DialogHandler.aspx" verb="*" type="Telerik.Web.UI.DialogHandler, Telerik.Web.UI" />
3. 分配路径
radContent.ImageManager.ViewPaths = New String() {"/DATA/path1", "/DATA/path2"}
radContent.ImageManager.UploadPaths = New String() {"/DATA/path1", "/DATA/path2"}

6. 优化 Dotnetnuke 配置

互联网上有许多资源讨论如何正确配置您的 DNN 网站。在这个小提示中,我只想强调一些要点:

  1. 将缓存设置选项设置为 Heavy:这将通过将所有页面、模块等缓存到内存中来提高性能。
  2. 页面状态持久性:对于小型网站,请使用 Memory 选项。对于大型复杂的网站,使用 Memory 选项可能会导致一些意外错误。请考虑使用 Page 选项,或者您需要自己构建缓存机制。
  3. 调度程序:将调度程序模式更改为 Timer Method,并禁用任何不需要的计划。
  4. 事件日志:在不需要时禁用日志记录。
  5. 调试模式:禁用调试模式(通过在 web.config 中将 Debug="False")。

7. 调优代码

  • 当我使用 ANTS Profiler 查看系统内部情况时,我发现每次调用 UserInfo 实例时 DNN 都会命中数据库(我不知道为什么 DNN 不缓存它)。
    我的解决方案是开发一个 Redis 缓存机制来存储所有用户、角色、我们的专业表等。
  • 另一点是:尽可能在 ASP.NET 控件中设置 EnableViewstate="False"。仅在需要从回发事件中获取控件值时将其设置为 True。这将大大减少渲染到客户端的流量。
  • 始终使用 SqlHelper 类访问数据库:它确保每次与 SQL Server 的连接都能正确关闭。

8. 调优 SQL 存储过程

使用 SQL Profiler 和 Tuning Adviser 来分析您的存储过程并对其进行优化。

尝试读取查询执行计划以实现最佳性能。

9. 使用缓存服务器

如上所述,尽量减少数据库命中次数。缓存服务器是最佳选择。考虑使用 Redis 或 Memcached(我正在使用 Redis)。如果您使用集群服务器,这一点尤其有用。

即使应用程序服务器重新启动,缓存仍然存在!

10. 使用 SQL 会话服务器

出于一致性的原因,使用 SQL 会话服务器。

使用的工具

  • ANTS Profiler
  • SQL Profiler & SQL Tuning Adviser

关注点

以上提示是我在使用 DNN 框架部署我的在线学习解决方案时发现有用且与其他不同的地方,希望对您有所帮助。

历史

  • 2014 年 10 月 2 日:初始版本
© . All rights reserved.