博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
FineUIPro v3.5.0发布了,减少 90% 的上行数据量,15行代码全搞定!
阅读量:6934 次
发布时间:2019-06-27

本文共 5629 字,大约阅读时间需要 18 分钟。

一切为客户着想

一切的一切还得从和一位台湾客户的沟通说起:

客户提到将ViewState保存在服务器端以减少上行数据量,从而加快页面的回发速度。

 

但是在FineUI中,控件状态都保存在FState中,并且为了减少下行数据量,FState的数据不仅用来保存状态,而且用于JavaScript的数据源。

所以FState必须写入HTTP响应,才能被JavaScript使用。我在之前的一篇文章中曾详细阐述:

 

但这的确是个问题,FState虽然能够减少下行数据量,但是页面回发时上行数据量依然很大,特别是页面中有多个下拉列表和表格时,上行的数据量可达到500K或者更多,对网速受限的环境的确是个挑战。

 

FineUI(专业版)v3.5.0将提供一种简单的方法,将FState保存在服务器端,从而大幅减少页面回发时的上行数据量。

 

注:FState仍然需要返回到页面上(以便JavaScript使用,比如作为表格和下拉列表的数据源),只不过不需要回发到服务器而已。

 

减少 90% 的上行数据

作为对比,我们以下面的表格页面为例:

 

首先选中一项,然后点击工具栏上的[删除选中行]按钮,此时会触发按钮点击事件,我们分别看下v3.3.0和v3.5.0中上传数据量。

FineUI(专业版)v3.3.0:

 

FineUI(专业版)v3.5.0:

 

FineUI(专业版)v3.3.0上行数据量:32616bytes =  31.9K

FineUI(专业版)v3.5.0上行数据量:2137bytes =  2.1K

 

从上面数据来看,FineUI(专业版)v3.5.0上行数据量减少了 90% 左右。在一个包含多个表格和下拉列表的页面,这个效果会更加明显。

 

自定义编码实现

虽然FineUI(专业版)v3.5.0提供了将FState保存到服务器端的方法,但不是默认就支持的,需要自己写点代码。因为保存到服务器有多种方法,可以保存到服务器文件中,HttpRuntime.Cache,SqlServer或者NoSQL数据库(比如Memcached,Redis)。

 

官网示例的PageBase.cs中提供了两种保存方式:文件、HttpRuntime.Cache,你可以直接拷贝代码到自己的项目中去。

现在来看下保存到服务器缓存中(HttpRuntime.Cache)的方法:

1. 启用PageManager的EnableFStatePersistence,并定义代理函数LoadFStateFromPersistenceMedium和SaveFStateToPersistenceMedium。

protected override void OnInit(EventArgs e){    var pm = PageManager.Instance;    if (pm != null)    {        // FState保存到服务器缓存        pm.EnableFStatePersistence = true;        pm.LoadFStateFromPersistenceMedium = LoadFStateFromPersistenceMedium_Cache;        pm.SaveFStateToPersistenceMedium = SaveFStateToPersistenceMedium_Cache;            }}

页面级别的支持,方便我们控制哪些页面启用,哪些页面可以不启用。

 

2. 获取和保存FState的代理函数

private static readonly string FSTATE_CACHE_KEY = "__FSTATE_KEY";private JObject LoadFStateFromPersistenceMedium_Cache(){    string cacheKey = Page.Request.Form[FSTATE_CACHE_KEY];    var fstate = HttpRuntime.Cache[cacheKey] as JObject;    if (fstate != null)    {        // 缓存使用过一次后,5s后过期(用不到了)        HttpRuntime.Cache.Insert(cacheKey, fstate, null,           DateTime.Now.AddSeconds(5),           System.Web.Caching.Cache.NoSlidingExpiration,           System.Web.Caching.CacheItemPriority.Default, null);    }        return fstate;}private void SaveFStateToPersistenceMedium_Cache(JObject fstate){
   // 1. 生成缓存Key = 用户会话ID+当前时间 string cacheKey = String.Format("{0}_{1}", HttpContext.Current.Session.SessionID, DateTime.Now.Ticks.ToString());    // 2. 将页面的FState保存到缓存中,指定过期时间为当前用户会话过期时间(Session.Timeout) // 指定时间后过期(Session.Timeout) HttpRuntime.Cache.Insert(cacheKey, fstate, null, DateTime.Now.AddMinutes(HttpContext.Current.Session.Timeout), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Default, null); // 3. 将缓存Key保存到页面的一个隐藏字段中,通过PageContext.RegisterStartupScript来注册一段脚本 PageContext.RegisterStartupScript(String.Format("F.setHidden('{0}','{1}');", FSTATE_CACHE_KEY, cacheKey));}

 

这里面的实现方式和在服务器端保存ViewState的方式类似。

 

官网示例中也有保存到服务器端文件的实现,可以参考:

private static readonly string FSTATE_FILE_KEY = "__FSTATE_KEY";private static readonly string FSTATE_FILE_BASE_PATH = "~/App_Data/FState/";private JObject LoadFStateFromPersistenceMedium(){    string filePath = GetFStateFilePath();    string fileContent;    using (StreamReader sr = new StreamReader(filePath, System.Text.Encoding.UTF8))    {        fileContent = sr.ReadToEnd();    }    return JObject.Parse(fileContent);}private void SaveFStateToPersistenceMedium(JObject fstate){    string filePath = GenerateFStateFilePath();    using (StreamWriter streamW = new StreamWriter(filePath, false, System.Text.Encoding.UTF8))    {        streamW.Write(fstate.ToString(Formatting.None));    }}private string GenerateFStateFilePath(){    DateTime now = DateTime.Now;    string folderName = now.ToString("yyyyMMddHH");    string fileName = String.Format("{0}_{1}",        HttpContext.Current.Session.SessionID,        now.Ticks.ToString());        //Page.Request.Url.AbsolutePath.Replace(".", "_").Replace("/", "_"));    string folderPath = Page.Server.MapPath(Path.Combine(FSTATE_FILE_BASE_PATH, folderName));    if (!Directory.Exists(folderPath))    {        Directory.CreateDirectory(folderPath);    }    PageContext.RegisterStartupScript(String.Format("F.setHidden('{0}','{1}');", FSTATE_FILE_KEY, fileName));    return folderPath + "/" + fileName + ".config";}private string GetFStateFilePath(){    string fileName = Request.Form[FSTATE_FILE_KEY];    string[] fileNames = fileName.Split('_');    string folderName = new DateTime(Convert.ToInt64(fileNames[1])).ToString("yyyyMMddHH");    return Page.Server.MapPath(Path.Combine(FSTATE_FILE_BASE_PATH, folderName)) + "/" + fileName + ".config";}

 

当然你也可以方便的扩展到外部数据库(SqlServer,MySql)以及NoSQL数据库(Memcached,Redis)。

 

使用建议

虽然EnableFStatePersistence可以极大的减少上行数据量,但并不适合于所有的场合。因为每个用户访问的每个页面都可能会产生大量的FState,所以在服务端保存意味着对服务器资源的极大消耗(内存、文件或者数据库)!

有一个简单的使用原则:

仅在上行带宽有限(也即是服务器成本低于网络传输成本)时使用,否则适得其反。

 

在 stackoverflow 上有,描述了将 ViewState 保存到服务器端可能存在的问题。

启用 FineUI 的 EnableFStatePersistence 适用于同样的原则(引文中的VS指的是ViewState):

  1. If the application recycles, the VS for all anyone using the application is lost.

  2. It increases the memory consumption of the application. This isn't an issue if there are only a few apps hosted on a server; but there are cases when there could be many websites hosted on one box.

  3. Scalability; the more active the application, the more VS needs to be stored. And you can't assume 1-1 (1 user - 1 VS). A user can have multiple tabs open, can go back, leave tabs inactive, etc... which leads to:

  4. How long do you store VS? Keeping the data encoded on the page ensures that it'll still be there if the user leaves the site open for a while.

  5. What happens if you're hosted on a web farm. We can't guarantee that the user will hit the same machine on each request.

 

 

官网示例:

 

 

转载地址:http://yfwnl.baihongyu.com/

你可能感兴趣的文章
Linux文件夹共享(NFS)
查看>>
桌面桌面虚拟化-Vmware 兼容性怎么查询
查看>>
docker的学习笔记(一)-一些基本的命令的学习
查看>>
JavaScript学习历程和心得
查看>>
Linux大文件处理,伪分区
查看>>
我的友情链接
查看>>
Hive 元数据表结构详解
查看>>
C#抽象工厂模式的几种实现方法及比较
查看>>
MYSQL启用日志,查看日志,利用mysqlbinlog工具恢复MySQL数据库
查看>>
OSPF分解试验部分-LAB7:NSSA区域
查看>>
Jedis使用示例
查看>>
Android关于绘图中Shader 的效果(中级)
查看>>
AlertDialog显示错误 Unable to add window token null is not for an application
查看>>
new二维数组的几种方法
查看>>
Ionic css组成(三)
查看>>
Python xrange与range的区别
查看>>
Aspose.Pdf 系列组件介绍
查看>>
easyopen原理解析——不到100行代码实现一个最精简的easyopen
查看>>
jsp 页面中El表达式失效处理
查看>>
srs-2-CentOS6 创建 Simple-Rtmp-Server
查看>>