成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

分享Web應用運行的細節問題

開發 前端
在這個文章里,我將分享一下在iOpenWorks.com這個網站試運行中碰到的若干問題和解決方案,這些問題包含了:(1)如果通過ASP.NET MVC預編譯提高性能;(2)如果知道網站在運行中,用戶響應速度、網站異常信息、用戶操作習慣;(3)解決與DiscuzToolkit集成的線程同步問題。

在這個文章里,我將分享一下在iOpenWorks.com這個網站試運行中碰到的若干問題和解決方案,這些問題包含了:(1)如果通過ASP.NET MVC預編譯提高性能;(2)如果知道網站在運行中,用戶響應速度、網站異常信息、用戶操作習慣;(3)解決與DiscuzToolkit集成的線程同步問題。

1 ASP.NET MVC 3預編譯支持

提高網站性能,除了我們常見的壓縮、CDN、緩存之外,還有一個就是使用預編譯。不管是ASP.NET WebForm,或者是ASP.NET MVC,這些頁面在網站運行過程中,都是要先經過編譯處理的。因此,如果能在網站運行前對其進行編譯,那無疑能更好的提高網站的響應速度。因此,我們選擇了一個RazorGenerator來對所有的ASP.NET MVC 3的視圖進行編譯,這樣,在部署時僅需要將dll文件拷貝過去,而不再需要cshtml文件了。下面介紹如何使用它來實現預編譯。

1.1 下載安裝RazorGenerator

你可以在http://razorgenerator.codeplex.com/下載到RazorGenerator,這是一個VS 2010的擴展。下載完成后,就可以直接安裝了。接著你還需要下載源代碼,然后編譯一下,獲取編譯的RazorGenerator.Mvc.dll程序集。

1.2 改變視圖文件的生成方式

將所有的視圖的BuildAction改成None,并且將CustomTool改成RazorGenerator,這時候,你可以看到一個關聯的.generated.cs文件,這個文件就是預編譯的源碼文件了。

image

1.3 處理Helper

對于Helpr文件,處理方式有所不同。Helper文件一般放在App_Code文件夾里面。首先,你需要在Helper文件的第一行添加 @* Generator: MvcHelper *@ 來聲明一下,接著將BuildAction改成None,并且將CustomTool改成RazorGenerator

image

下面,還需要額外一個步驟,這個非常重要,否則編譯無法通過,那就是需要將.generated.cs文件的BuildAction由Content改為Compile。

image

1.4 注冊PrecompiledMvcEngine

下面我們在ASP.NET MVC 3項目中引用RazorGenerator.Mvc.dll這個程序集,然后定義一個PreApplicationStartCode,并在AssemblyInfo.cs文件中注冊這個PreApplicationStartCode。這樣,我們就注冊了PrecompiledMvcEngine了。

(1)在AssemblyInfo.cs注冊

  1. [assembly: PreApplicationStartMethod(   
  2.     typeof(UIShell.iOpenWorks.PreApplicationStartCode), "PreStart")] 

(2)PreApplicationStartCode定義

  1. namespace UIShell.iOpenWorks   
  2. {   
  3.     public class PreApplicationStartCode   
  4.     {   
  5.         private static bool _isStarting;  
  6.         public static void PreStart()   
  7.         {   
  8.             if (!_isStarting)   
  9.             {   
  10.                 _isStarting = true;  
  11.                 var engine = new PrecompiledMvcEngine(   
  12.                     typeof(PreApplicationStartCode).Assembly);  
  13.                 ViewEngines.Engines.Add(engine);  
  14.                 VirtualPathFactoryManager.RegisterVirtualPathFactory(engine);   
  15.             }   
  16.         }   
  17.     }   

1.5 部署

這時候,部署網站就不再需要將視圖文件部署過去了,只需要拷貝dll文件和網站資源。注意,在Views下面已經沒有.cshtml文件了,也沒有App_Code文件,因為它們都被預編譯到了UIShell.iOpenWorks.dll這個程序集了。接下來,你就可以測試一下網站,享受一下預編譯帶來的性能提升了。

imageimage

2 跟蹤網站運行情況

網站在內測期間,會碰到較多的問題。但是,這時候,用戶已經進來測試,你怎么能夠及時發現用戶響應速度、用戶訪問過程中網站異常信息以及用戶是如何來使用你的網站。這里,我們使用了log4net這個日志組件,它用于記錄:(1)用戶訪問了哪些頁面;(2)用戶在訪問頁面過程中,碰到了哪些異常;(3)每一個頁面的響應速度。下面,我來介紹如何記錄這些信息的。

2.1 在Global中,跟蹤每個用戶訪問的頁面,并且要記錄用戶響應的速度

  1. [ThreadStatic]   
  2. private static Stopwatch _stopwatch;  
  3. protected void Application_BeginRequest()   
  4. {   
  5.     _stopwatch = Stopwatch.StartNew();  // 計時開始   
  6.     if (DiscuzHelper.IsLoggedIn()) // 記錄當前用戶   
  7.     {   
  8.         try   
  9.         {   
  10.             var user = DiscuzHelper.LoggedUser();   
  11.             if(user != null)   
  12.             {   
  13.                 ThreadContext.Properties["user"] = user.UserName;   
  14.                 return;   
  15.             }   
  16.         }   
  17.         catch (Exception ex)   
  18.         {   
  19.             _logger.Error("Failed to get the user name though the user is logged in.", ex);   
  20.         }   
  21.     }   
  22.               
  23.     ThreadContext.Properties["user"] = string.Empty;  
  24.     if (Request != null) // 記錄當前用戶的IP   
  25.     {   
  26.         ThreadContext.Properties["ipaddress"] = Request.ServerVariables["REMOTE_ADDR"];   
  27.     }   
  28.     else   
  29.     {   
  30.         ThreadContext.Properties["ipaddress"] = string.Empty;   
  31.     }   
  32. }  
  33. protected void Application_EndRequest()   
  34. {   
  35.     if (Request != null && _stopwatch != null && _logger != null)  // 計時結束,就用戶響應時間和訪問頁面   
  36.     {   
  37.         _stopwatch.Stop();   
  38.         _logger.Debug(string.Format("Accessed page 'Response time: {0} ms, Url: {1}'.", _stopwatch.ElapsedMilliseconds, Request.Url));   
  39.     }   

2.2 在Global中,記錄系統的異常

  1. void Application_Error(Object sender, EventArgs ea)   
  2. {   
  3.     if (Server != null)   
  4.     {   
  5.         Exception e;   
  6.         for (e = Server.GetLastError(); e != null; e = e.InnerException)   
  7.         {   
  8.             _logger.Error("Unhandled server exception thrown.", e);   
  9.         }   
  10.     }   

2.3 處理關鍵方法

下面,我還在關鍵方法記錄了用戶的操作異常信息、響應速度。比如我必須記錄了:(1)用戶注冊時響應速度、注冊時發生的異常、用戶登錄時響應速度、用戶登錄時發生的異常;(2)用戶在什么情況下嘗試下載iOpenWorksSDK這個免費插件框架;(3)嘗試下載時,會轉到注冊頁面,這時候用戶是否繼續注冊并下載,還是放棄。

對這些關鍵方法的記錄,有助于提高應用系統的易用性。通過日志,我們修復了與Discuz集成的很多問題,并且提高了用戶響應速度。

2.4 日志分析

下面,我們需要來看一下日志分析,這里我們在一個開源的LogViewer自定義了一下。通過對日志的分析,你就可以知道系統發生了什么異常、系統性能如何、用戶操作習慣、關鍵方法的信息。當然,你也可以打開日志文件直接查看,只是,那樣比較費勁。對了,在這里我們絕不記錄用戶的密碼,這太不職業道德了,此外,所有密碼都是加密的,避免“CSDN”!

(1)查看異常信息

image

(2)查看關鍵方法信息:用戶訪問習慣、響應性能等

image

3 解決DiscuzToolkit線程同步

網站的社區是與Discuz集成的,我們就用了DiscuzToolkit來集成。這是官方發布的類庫,但是依然問題一堆。最嚴重的2個問題就是線程同步引起的,可見Discuz這幫人都ASP.NET多線程模型壓根沒有當一回事,或者連線程安全都沒有注意到。下面就說一下碰到的2個線程安全問題。

(1)在注冊用戶時,碰到以下異常:當前會話所提交的call_id沒有大于前一次的call_id

Failed to get the user name though the user is logged in.
Discuz.Toolkit.DiscuzException: Code: 103, Message: 當前會話所提交的call_id沒有大于前一次的call_id
at Discuz.Toolkit.Util.GetResponse[T](String method_name, DiscuzParam[] parameters) in E:\Work\Design\Core\milestore 1\osgi\m10\uishell.iopenworks\DiscuzToolkit\Util.cs:line 97
at Discuz.Toolkit.DiscuzSession.GetUserInfo(Int64[] uids, String[] fields) in E:\Work\Design\Core\milestore 1\osgi\m10\uishell.iopenworks\DiscuzToolkit\DiscuzSession.cs:line 224
at Discuz.Toolkit.DiscuzSession.GetUserInfo(Int64 uid) in E:\Work\Design\Core\milestore 1\osgi\m10\uishell.iopenworks\DiscuzToolkit\DiscuzSession.cs:line 255

這個問題是由Discuz.Toolkit.Util的Sign方法引起的,在這里,它為每一個API請求生成一個call_id。

  1. list.Add(DiscuzParam.Create("call_id", DateTime.Now.Ticks)); 

如果你在當前線程API調用太勤快的話,DateTime.Now.Ticks會生成一樣的值,從而引發異常。因此,官方提議可以Sleep一下。因此,我們就需要改成如下:

  1. list.Add(DiscuzParam.Create("call_id", DateTime.Now.Ticks));   
  2. // Avoid to generate same 'call_id' and throws an exception on '當前會話所提交的call_id沒有大于前一次的call_id'.   
  3. Thread.Sleep(50); 

但是這樣,依然是不過的,這個異常只是變得更加詭異了,讓你碰到機會少一點而已。你別忘了ASP.NET應用程序是多線程的,當兩個線程同時訪問時,依然可能獲得同一個call_id,于是,在碰到若干次這個問題后,我用以下方法來修復。

  1. lock (_syncRoot)   
  2. {   
  3.     list.Add(DiscuzParam.Create("call_id", DateTime.Now.Ticks));   
  4.     // Avoid to generate same 'call_id' and throws an exception on '當前會話所提交的call_id沒有大于前一次的call_id'.   
  5.     Thread.Sleep(50);   

(2)注冊用戶時,碰到以下異常:An item with the same key has already been added.

[2012-04-07 17:11:30,818] [7] [ERROR] [AccountController] [49.72.46.135] []: System.ArgumentException: An item with the same key has already been added.
at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
at Discuz.Toolkit.Util.GetSerializer(Type t) in E:\Work\Design\Core\milestore 1\osgi\m10\uishell.iopenworks\DiscuzToolkit\Util.cs:line 157
at Discuz.Toolkit.Util.GetResponse[T](String method_name, DiscuzParam[] parameters) in E:\Work\Design\Core\milestore 1\osgi\m10\uishell.iopenworks\DiscuzToolkit\Util.cs:line 88
at Discuz.Toolkit.DiscuzSession.GetUserID(String username) in E:\Work\Design\Core\milestore 1\osgi\m10\uishell.iopenworks\DiscuzToolkit\DiscuzSession.cs:line 243
at UIShell.iOpenWorks.Controllers.AccountController.Register(DiscuzNewUser newUser, String returnUrl) in E:\Work\Design\Core\milestore 1\osgi\m10\uishell.iopenworks\UIShell.iOpenWorks\Controllers\AccountController.cs:line 53

你想想,要是用戶注冊時,動不動碰到注冊不成功,是多么窩火!!所以,我根據日志再次調查發現,DiscuzToolkit在使用靜態變量保存數據時,竟然不加鎖,太不拿Thread-Safe當回事了。這會異常也發生在Util類里,代碼如下,其中serializer_dict是靜態全局變量。

  1. serializer_dict.Add(type_hash, new XmlSerializer(t)); 

于是,我修改如下。這樣,徹底解決了和Discuz的集成了。

  1. private static Dictionary<int, XmlSerializer> serializer_dict = new Dictionary<int, XmlSerializer>();   
  2. private static ReaderWriterLock _lock = new ReaderWriterLock();   
  3. public static XmlSerializer GetSerializer(Type t)   
  4. {   
  5.     int type_hash = t.GetHashCode();   
  6.     const int timeout = 5000;  
  7.     try   
  8.     {   
  9.         _lock.AcquireReaderLock(timeout);   
  10.         if (!serializer_dict.ContainsKey(type_hash))   
  11.         {   
  12.             _lock.UpgradeToWriterLock(timeout);   
  13.             if (!serializer_dict.ContainsKey(type_hash))   
  14.             {   
  15.                 serializer_dict.Add(type_hash, new XmlSerializer(t));   
  16.             }   
  17.         }  
  18.         return serializer_dict[type_hash];   
  19.     }   
  20.     catch (ApplicationException ex)   
  21.     {   
  22.         throw new Exception("Accquire lock failed.", ex);   
  23.     }   
  24.     finally   
  25.     {   
  26.         if (_lock.IsReaderLockHeld)   
  27.         {   
  28.             _lock.ReleaseReaderLock();   
  29.         }   
  30.         else if (_lock.IsWriterLockHeld)   
  31.         {   
  32.             _lock.ReleaseWriterLock();   
  33.         }   
  34.     }   

OK,關于網站試運行中,最重要的幾點分享描述完了。順道介紹一下什么是iOpenWorks.com。iOpenWorks.com是一個免費工廠的開放倉庫,旨在向開發人員提供完全免費的標準化的OSGi.NET面向服務插件框架以及共享的插件倉庫,這樣,你既可以從插件倉庫使用別人插件,也可以共享自己的插件,互利共贏!

你也可以加入iOpenWorks交流群:121369588,Thanks。

原文鏈接:http://www.cnblogs.com/baihmpgy/archive/2012/04/09/2438720.html

【編輯推薦】

  1.  10個基于Web的HTML5音樂播放器
  2. 淺談Web自動化測試原理
  3. 分享21個最新的超酷web設計特效
  4. 開發者應該關注的五項Web新興技術
  5. 手機WEBKIT引擎HTML元素定位和事例
責任編輯:林師授 來源: 陳貞寶的博客
相關推薦

2011-03-28 10:05:20

細節PlayBookAndroid

2009-12-29 16:08:41

Silverlight

2009-10-22 11:03:20

OSGi Web應用程

2020-11-04 13:18:34

WebAPIWeb Share A

2014-05-26 09:13:46

DockerPython

2023-11-20 08:02:49

2010-05-28 10:23:59

JavaScriptWeb

2011-03-25 11:06:46

2011-10-28 13:34:10

iPhone應用設計

2023-01-03 10:30:00

Java工具

2010-04-28 17:01:30

Apusic負載均衡器

2011-05-27 17:28:27

nofollowSEO

2015-10-14 10:03:28

Web應用云服務PaaS

2009-01-15 09:43:51

Web架構設計緩存

2012-03-24 20:40:16

Windows 8

2010-07-26 08:46:21

PHP負載均衡

2012-12-24 09:55:24

Web應用云計算

2014-08-26 10:29:31

2010-06-23 08:56:58

ASP.NET MVC

2022-02-02 21:50:25

底層偽共享CPU
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲一区二区三区视频免费观看 | 欧美人妇做爰xxxⅹ性高电影 | av日韩在线播放 | 91麻豆精品国产91久久久资源速度 | 国产激情免费视频 | 精品国产一级 | 成人在线精品视频 | 亚洲综合色自拍一区 | 国产成人综合一区二区三区 | 欧美色综合一区二区三区 | 久久久久99 | 久久毛片 | 精品国产成人 | 91久久精品一区二区三区 | 久久久久久久久久久高潮一区二区 | 黄色高清视频 | 国产精品激情 | 日韩中文字幕一区二区 | 日本亚洲一区 | 亚洲精品乱码久久久久久9色 | 成人欧美一区二区三区在线观看 | 成人免费大片黄在线播放 | 亚洲精品久久 | 玖玖玖在线观看 | 日韩一区二区三区在线观看 | 欧美在线观看一区 | 亚洲天堂999 | 91精品国产色综合久久不卡98口 | 日韩在线小视频 | 性做久久久久久免费观看欧美 | 一级免费毛片 | 久久国产精品免费 | 亚洲成人一二区 | 久热免费在线 | 国产精品久久在线观看 | 亚洲精品成人在线 | 国产精品色av | 少妇午夜一级艳片欧美精品 | 日本天堂视频在线观看 | 毛片免费看的 | 先锋资源网站 |