调整程序架构的思维 记改进程序缓存的经历

开发 架构
写程序超过10年的企业内部管理系统,今年开始总算是彻底走向web网络编程了,但是由于以前的一些老的思想还没彻底抛弃,导致写程序的思维有时候还有一些老旧。下面从一些思维的转变开始谈起。

实际情况:

1:当公司的网站访问量达到每天几十万IP时,网站服务器的压力就非常大,一个非常简单的程序,相邻的2个sql语句,在服务器繁忙时,可能会过3-5分钟才能运行完毕,甚至更长时间。服务器的硬件配置也已经足够高了,这时候几乎无法靠平常的数据库的读写,数据库的优化来提高程序的性能的。

2:硬盘的转速是有限的,当数据库量已经很大时,数据库读取数据也耗费很多时间。而且加硬盘相对比加内存条更复杂一些。

3:当数据库的索引优化,分区优化都已经用完了,数据库的结构也不能随便修改时,靠数据库优化的就遇到了瓶颈了。

4:现在内存都比较便宜,服务器上把能插内存条的地方都可以插满了,但是系统往往不会用掉所有的内存,内存空间还是可以有富足。

5:虽然也可以用很多第3方组件来达到优化的目的,但是需要有学习成本,有采购成本,再有后期的维护成本,服务器的性能同样也是增加压力。

6:目前服务器的压力已经快崩溃了,也比较难提升性能时,再有比较复杂的权限计算,每刷新一个页面时,还判断10次8次以上操作权限项目,需要更多的I/O时,很可能系统就真的彻底崩溃了。

7:当然我们可以在另外购买服务器,把程序的压力进行分担,但是我们假设不购买硬件了,数据库也必须需要用同一个,从同一个服务器上的数据库需要读取数据。

在上面的程序环境下,就是老顽固也需要转变思维了。

1:老顽固都比较难转变思想:

因为事实摆在眼前,就是老顽固也必须接纳缓存的做法了,虽然缓存有时候很折磨人,但是不靠缓存已经很难解决问题了。虽然以前有很多人给我过这样的建议,都没放在心上。

2:程序的及时性思维的转变:

以前写程序都强调,数据设置发生了变化程序能马上显示出来效果,例如修改了某个人的权限设置后,马上就生效了。其实有时候没必要那么马上生效。有必要时刷新一下缓存,若没必要用户下次登录时就生效了,顶多若有问题用户再登录一次就可以了,权限设置又不是每时每刻都在设置的,很多时候设置好了,半年一年都不用设置,没必要过分强调实时性。

其实程序员都有过度设计的问题,用户权限方面,我也的确是想的有些过度了,其实稍微放宽一下,也能满足正常的日常使用的,顶多加个刷新缓存的功能,若有必要马上见效就马上刷洗一下缓存就可以了。

3:在不提高,就倍很多年轻人彻底超越了:

奔35了,体力脑力都明显大幅下降,明显感觉到身边的年轻人又聪明又能干,这时候自己再不提高,很容易就彻底走下坡路了。虽然难起领头羊的作用,但是至少不要被大家彻底甩在后面去了。

4:马上动手改进程序:

有了想法了就需要马上动手,架构良好的程序都经得起重构才对,所以一直认为自己的程序架构是非常良好的,那就应该能经得起修改才对,架构好的程序应该不是全盘推倒从来,而是小修改几个函数就应该能达到内存缓存的目的。

5:新系统要上线要靠谱的测试确认:

程序更新上去后,前后至少要测试1周,各种功能都稳定,数据都正确才能正式投入实际实用。 

    吉日嘎拉,通用权限管理系统组件 

接着就是程序修改的部分:

其实总共就写了300行不到的代码,系统的本质的改造就完成了。

1:用户能访问的模块菜单,用户拥有的操作权限项,改进为泛型。

           protected List<BaseModuleEntity> ModuleList

           protected List<BasePermissionItemEntity> PermissionItemList

2:当用户需要判断权限时,一次性把权限读取到Cache缓存中。

3:权限判断函数改进为从内存Cache缓存进行判断。

4:用户退出时,把相应的内存缓存清除掉,减轻内存的压力。

5:写个刷新缓存的功能,有需要时,对所有的缓存进行实时的刷新。

有时候代码也就300行不到还有一大堆是注释,有一大堆是没用的,还有一大堆是重复的,真正有价值的代码可能不超过50行,但是里面有蛮多故事,有故事的代码更有生命力,有故事的代码就更有卖点,有故事的代码经常更经得起考验,欢迎大家拍砖,大家一起学习提高,在交流中不断修正代码,不断提高自己,不断改进错误,一天比一天强大。

  1. //----------------------------------------------------------------- 
  2.  // All Rights Reserved , Copyright (C) 2012 , Hairihan TECH, Ltd . 
  3.  //----------------------------------------------------------------- 
  4.   
  5.  using System; 
  6.  using System.Collections.Generic; 
  7.  using System.Linq; 
  8.  using System.Web; 
  9.   
  10.  using DotNet.Business; 
  11.   
  12.  /// <remarks> 
  13.  /// BasePage 
  14.  /// 基础网页类 
  15.  ///  
  16.  /// 修改纪录 
  17.  ///  
  18.  ///    版本:1.0 2012.11.10    JiRiGaLa    整理代码。 
  19.  ///     
  20.  /// 版本:1.0 
  21.  /// <author>   
  22.  ///        <name>JiRiGaLa</name> 
  23.  ///        <date>2012.11.10</date> 
  24.  /// </author>  
  25.  /// </remarks> 
  26.  public partial class BasePage : System.Web.UI.Page 
  27.  { 
  28.      /// <summary> 
  29.      /// 用户锁 
  30.      /// </summary> 
  31.      public static readonly object UserLock = new object(); 
  32.   
  33.      #region 常用操作权限项定义 
  34.   
  35.      /// <summary> 
  36.      /// 访问权限 
  37.      /// </summary> 
  38.      protected bool permissionAccess = true
  39.   
  40.      /// <summary> 
  41.      /// 新增权限 
  42.      /// </summary> 
  43.      protected bool permissionAdd = true
  44.   
  45.      /// <summary> 
  46.      /// 编辑权限 
  47.      /// </summary> 
  48.      protected bool permissionEdit = true
  49.   
  50.      /// <summary> 
  51.      /// 删除权限 
  52.      /// </summary> 
  53.      protected bool permissionDelete = true
  54.   
  55.      /// <summary> 
  56.      /// 查询权限 
  57.      /// </summary> 
  58.      protected bool permissionSearch = true
  59.   
  60.      /// <summary> 
  61.      /// 管理权限 
  62.      /// </summary> 
  63.      protected bool permissionAdmin = false
  64.   
  65.      /// <summary> 
  66.      /// 导出权限 
  67.      /// </summary> 
  68.      protected bool permissionExport = true
  69.   
  70.      /// <summary> 
  71.      /// 导入权限 
  72.      /// </summary> 
  73.      protected bool permissionImport = true
  74.   
  75.      /// <summary> 
  76.      /// 打印权限 
  77.      /// </summary> 
  78.      protected bool permissionPrint = true
  79.   
  80.      #endregion 
  81.       
  82.      // 用户是否在某个角色里(按编号,按名称的) 
  83.   
  84.      #region public bool UserIsInRole(string roleCode) 
  85.      /// <summary> 
  86.      /// 用户是否在某个角色里 
  87.      /// </summary> 
  88.      /// <param name="roleCode">角色编号</param> 
  89.      /// <returns>是否在某个角色里</returns> 
  90.      public bool UserIsInRole(string roleCode) 
  91.      { 
  92.          BaseUserManager userManager = new BaseUserManager(this.UserCenterDbHelper, userInfo); 
  93.          return userManager.IsInRoleByCode(this.UserInfo.Id, roleCode); 
  94.      } 
  95.      #endregion 
  96.       
  97.      // 用户操作权限常用判断函数 
  98.   
  99.      #region public void Authorized(string permissionItemCode, string accessDenyUrl = null) 是否有相应权限,同时若没权限会重新定位到某个页面 
  100.      /// <summary> 
  101.      /// 是否有相应权限,同时若没权限会重新定位到某个页面 
  102.      /// </summary> 
  103.      /// <param name="permissionItemCode">权限编号</param> 
  104.      /// <param name="accessDenyUrl">访问被阻止的url</param> 
  105.      public void Authorized(string permissionItemCode, string accessDenyUrl = null
  106.      { 
  107.          // 若没有相应的权限,那就跳转到没有权限的页面里 
  108.          if (!Utilities.UserIsLogOn() || !IsAuthorized(permissionItemCode)) 
  109.          { 
  110.              if (!string.IsNullOrEmpty(accessDenyUrl)) 
  111.              { 
  112.                  HttpContext.Current.Response.Redirect(accessDenyUrl); 
  113.              } 
  114.              else 
  115.              { 
  116.                  HttpContext.Current.Response.Redirect(Utilities.AccessDenyPage + "?PermissionItemCode=" + permissionItemCode); 
  117.              } 
  118.          } 
  119.      } 
  120.      #endregion 
  121.   
  122.      #region public bool IsAuthorized(string permissionItemCode, string permissionItemName = null) 是否有相应的权限 
  123.      /// <summary> 
  124.      /// 是否有相应的权限 
  125.      /// </summary> 
  126.      /// <param name="permissionItemCode">权限编号</param> 
  127.      /// <returns>是否有权限</returns> 
  128.      public bool IsAuthorized(string permissionItemCode, string permissionItemName = null
  129.      { 
  130.          return IsAuthorized(this.UserInfo.Id, permissionItemCode, permissionItemName); 
  131.      } 
  132.   
  133.      public bool IsAuthorized(string userId, string permissionItemCode, string permissionItemName = null
  134.      { 
  135.          // 是否从服务器缓存读取用户权限 
  136.          bool fromCache = true
  137.          if (fromCache) 
  138.          { 
  139.              // 这里也可以优化一下,没必要遍历所有的操作权限列表 
  140.              int count = this.PermissionItemList.Count(entity => !string.IsNullOrEmpty(entity.Code) && entity.Code.Equals(permissionItemCode, StringComparison.OrdinalIgnoreCase)); 
  141.              return count > 0; 
  142.          } 
  143.          // 实时从数据库读取操作权限的设置方法 
  144.          DotNetService dotNetService = new DotNetService(); 
  145.          return dotNetService.PermissionService.IsAuthorizedByUser(this.UserInfo, userId, permissionItemCode, permissionItemName); 
  146.      } 
  147.      #endregion 
  148.   
  149.      #region protected void GetPermissionItemList() 获用户拥有的操作权限列表 
  150.      /// <summary> 
  151.      /// 获用户拥有的操作权限列表 
  152.      /// </summary> 
  153.      protected void GetPermissionItemList() 
  154.      { 
  155.          // 这里是控制用户并发的,减少框架等重复读取数据库的效率问题 
  156.          lock (BasePage.UserLock) 
  157.          { 
  158.              string cacheKey = "P" + this.UserInfo.Id; 
  159.              if (HttpContext.Current.Session == null || Cache[cacheKey] == null
  160.              { 
  161.                  // 这个是默认的系统表名称 
  162.                  DotNetService dotNetService = new DotNetService(); 
  163.                  PermissionItemList = dotNetService.PermissionService.GetPermissionItemListByUser(this.UserInfo, this.UserInfo.Id); 
  164.              } 
  165.          } 
  166.      } 
  167.      #endregion 
  168.   
  169.      #region protected List<BasePermissionItemEntity> PermissionItemList 获用户拥有的操作权限列表 
  170.      /// <summary> 
  171.      /// 获用户拥有的操作权限列表 
  172.      /// </summary> 
  173.      protected List<BasePermissionItemEntity> PermissionItemList 
  174.      { 
  175.          get 
  176.          { 
  177.              lock (BasePage.UserLock) 
  178.              { 
  179.                  // 这里进行了操作权限优化,出错问题 
  180.                  this.GetPermissionItemList(); 
  181.              } 
  182.              string cacheKey = "P" + this.UserInfo.Id; 
  183.              return Cache[cacheKey] as List<BasePermissionItemEntity>; 
  184.          } 
  185.          set 
  186.          { 
  187.              string cacheKey = "P" + this.UserInfo.Id; 
  188.              Cache[cacheKey] = value; 
  189.          } 
  190.      } 
  191.      #endregion 
  192.       
  193.      // 用户模块菜单权限判断常用函数 
  194.   
  195.      #region public void ModuleAuthorized(string moduleCode, string accessDenyUrl = null) 是否有相应的模块权限,同时若没权限会重新定位到某个页面 
  196.      /// <summary> 
  197.      /// 是否有相应的模块权限,同时若没权限会重新定位到某个页面 
  198.      /// </summary> 
  199.      /// <param name="moduleCode">模块编号</param> 
  200.      /// <param name="accessDenyUrl">访问被阻止的url</param> 
  201.      public void ModuleAuthorized(string moduleCode, string accessDenyUrl = null
  202.      { 
  203.          // 若没有相应的权限,那就跳转到没有权限的页面里 
  204.          if (!Utilities.UserIsLogOn() || !IsModuleAuthorized(moduleCode)) 
  205.          { 
  206.              if (!string.IsNullOrEmpty(accessDenyUrl)) 
  207.              { 
  208.                  HttpContext.Current.Response.Redirect(accessDenyUrl); 
  209.              } 
  210.              else 
  211.              { 
  212.                  HttpContext.Current.Response.Redirect(Utilities.AccessDenyPage + "?ModuleCode=" + moduleCode); 
  213.              } 
  214.          } 
  215.      } 
  216.      #endregion 
  217.   
  218.      #region public bool IsModuleAuthorized(string moduleCode) 是否有相应的模块权限 
  219.      /// <summary> 
  220.      /// 是否有相应的模块权限 
  221.      /// </summary> 
  222.      /// <param name="moduleCode">模块编号</param> 
  223.      /// <returns>是否有权限</returns> 
  224.      public bool IsModuleAuthorized(string moduleCode) 
  225.      { 
  226.          if (this.UserInfo.IsAdministrator) 
  227.          { 
  228.              return true
  229.          } 
  230.          // 这里也可以优化一下,没必要遍历所有的模块列表 
  231.          int count = this.ModuleList.Count(entity => !string.IsNullOrEmpty(entity.Code) && entity.Code.Equals(moduleCode, StringComparison.OrdinalIgnoreCase)); 
  232.          return count > 0; 
  233.      } 
  234.      #endregion 
  235.   
  236.      #region protected void GetModuleList() 获用户有访问权限的模块列表 
  237.      /// <summary> 
  238.      /// 获用户有访问权限的模块列表 
  239.      /// </summary> 
  240.      protected void GetModuleList() 
  241.      { 
  242.          // 这里是控制用户并发的,减少框架等重复读取数据库的效率问题 
  243.          lock (BasePage.UserLock) 
  244.          { 
  245.              string cacheKey = "M" + this.UserInfo.Id;  
  246.              if (HttpContext.Current.Session == null || Cache[cacheKey] == null
  247.              { 
  248.                  // 这个是默认的系统表名称 
  249.                  DotNetService dotNetService = new DotNetService(); 
  250.                  ModuleList = dotNetService.PermissionService.GetModuleListByUser(this.UserInfo, this.UserInfo.Id); 
  251.              } 
  252.          } 
  253.      } 
  254.      #endregion 
  255.   
  256.      #region protected List<BaseModuleEntity> ModuleList 获用户有访问权限的模块列表 
  257.      /// <summary> 
  258.      /// 获用户有访问权限的模块列表 
  259.      /// </summary> 
  260.      protected List<BaseModuleEntity> ModuleList 
  261.      { 
  262.          get 
  263.          { 
  264.              lock (BasePage.UserLock) 
  265.              { 
  266.                  // 这里进行了菜单优化,出错问题 
  267.                  this.GetModuleList(); 
  268.              } 
  269.              string cacheKey = "M" + this.UserInfo.Id;  
  270.              // return Utilities.GetFromSession("UserModuleList") as List<BaseModuleEntity>; 
  271.              return Cache[cacheKey] as List<BaseModuleEntity>; 
  272.          } 
  273.          set 
  274.          { 
  275.              string cacheKey = "M" + this.UserInfo.Id; 
  276.              Cache[cacheKey] = value; 
  277.              // Utilities.AddSession("UserModuleList", value); 
  278.          } 
  279.      } 
  280.      #endregion 
  281.  } 

原文链接:http://www.cnblogs.com/jirigala/archive/2012/11/12/2766952.html

【编辑推荐】

责任编辑:彭凡 来源: 博客园
相关推荐

2012-06-20 14:07:28

多线程架构单线程

2021-08-25 15:32:47

脚本程序参数任务

2019-01-02 07:36:28

微软 Windows 程序员

2022-12-03 17:14:03

裁员MQ集群

2009-01-20 23:27:55

程序员创业思维障碍

2013-03-28 15:24:29

程序员

2020-07-24 07:44:10

程序员思维逆向

2013-04-01 10:27:37

程序员失业

2021-11-24 11:04:09

技术架构技术前线 IT管理

2013-01-17 10:31:13

JavaScriptWeb开发firebug

2013-05-27 15:57:36

逻辑思维

2018-01-26 14:35:16

程序员入门经历

2013-05-31 09:05:47

2017-11-27 11:26:35

程序员Bug调试

2022-08-30 08:13:30

流程模板定期复盘数据

2018-09-28 14:12:48

小程序

2017-11-10 14:00:39

Riverbed应用程序网络性能

2009-01-03 14:25:10

ibmdwWeb

2020-03-02 09:50:50

程序员技能开发者

2023-11-27 09:25:42

程序员思维
点赞
收藏

51CTO技术栈公众号