前言
公司系統雖然配置有1臺NLB后拖4臺App Server最后搭一臺強勁無比的DB Server,但每天下午4點左右總被投訴系統慢,報表下載不了等問題。究其原因,原來NLB采用鎖定sessionId轉發請求,而IIS的最大工作進程數卻是1而已,只能通過增加工作線程的方式來提高并發量,但增加線程會消耗更多內存,當所占內存接近2G時應用48%左右的執行時間被分配給GC工作了,也就是說負載增大時上述硬件配置并然卵。那解決方案明顯如下:
1. NLB采用實際負載請求轉發請求;
2. IIS采用WebGarden模式;
3. 多臺IIS組成WebFarm;
4. 為實現IIS的WebGarden和WebFarm工作模式,需要配置啟用StateServer。
另外,由于前期開發階段大家并不清楚采用IIS WebGarden模式運行所帶來的限制,因此還要對代碼進行分析、調整。
本文作為上段時間工作內容時查閱資料的整理總結,以便日后查閱。
何為WebGarden & WebFarm?
IIS默認配置下采用的是單工作進程的工作模式,也就是只啟用一個w3wp.exe進程處理所有請求,然后進程內啟用多個線程來處理并發請求,最大工作線程數由具體的操作系統和IIS來決定,當并發量大于線程數時則會讓請求排隊等待處理。這是面對高并發量,且部分請求處理耗時較長時就會造成大部分請求長期處于掛起的狀態,用戶感知就是慢,TMD慢。。。。
WebGarden其實就是IIS的多工作進程的工作模式,而WebFarm則是多臺IIS應用服務器作負載均衡。
默認情況下(No WebGarden, No WebFarm):
WebGarden:
WebFarm:
配置WebGarden
在IIS 6中,右鍵單擊“應用程序池” > “屬性” > 轉到“性能”選項卡。在“性能”選項卡部分,有一個“Web Garden”的選項,默認值為“1”,您可以將該值設置為您需要的數值。
在IIS 7中,右鍵單擊“應用程序池” > 轉到“高級設置” > 找到“進程模型”,下面有個“最大工作進程”項。
開啟WebGarden是不是很簡單呢?那問題落在到底maxWorkerProcesses設置多少才適合呢?一般建議設置為“邏輯核數”即可。
到底WebGarden針對哪種場景,又有什么好處呢?
對于上述的問題,我想前IIS PM Chris Adams給出的答案會更準確(http://blogs.iis.net/chrisad/1342059)
Web gardens was designed for one single reason – Offering applications that are not CPU-bound but execute long running requests the ability to scale and not use up all threads available in the worker process.
從Chris Adams處我們可知WebGarden的目的是針對大量長鏈接的情景,通過增加工作進程來增加可用的工作線程。
另外,我想大家都有過這樣的經歷。maximum worker processes為1時,并發量上揚時w3wp.exe所占的內存(專用工作集/專用字節)會急速上升,當所占內存接近2GB時響應延時就變得十分嚴重,唯一的辦法就是等待、等待、等待。。。。。。要不就回收進程釋放內存,但這時會中斷用戶的請求。
那為什么會這樣呢?
1. 首先需要明確的是 工作線程 對應 請求 是一一對應的,因此當接收到N個請求時,就會開啟N個工作線程處理請求,若請求量超過最大工作線程數時則會讓請求排隊;
2. 線程本身也占內存資源,就線程棧空間而言,IIS5/6每個線程棧空間就占256KB,而Windows Server 2000下則占1MB。對于Windows Server 2008下的IIS7而言,32bit則占256KB,64bit則占512KB。極端情況下即使新開的線程所處理的程序入參和局部變量只使用1KB,但線程棧依然會占512KB。更不用說程序中還用到大量堆空間的對象了;
3. 進程是分配內存資源的最小單位,也就所有工作線程均使用同一塊內存空間,更重要的是所有工作線程采用同一套GC機制,那么當執行GC時將掛起所有工作線程;
4. 雖然Windows Server2008 64Bit對進程所占的內存空間沒有設置上限,但若進程所占內存空間大且托管堆中含大量一次性對象那么必然會引起頻繁的GC操作。(極端情況下GC占進程的執行時間片的48%左右)
也就是我們通過“任務管理器”查看w3wp.exe內存占用率升高時,響應延時增大的根本原因是:工作進程中托管堆存在大量臨時對象,導致頻繁執行GC操作,而GC操作執行時會掛起所有工作線程,導致請求處理的延時增大。
而WebGarden就是將工作線程均勻分配到多個工作進程中,那么各工作進程所占用的內存相對較少,減少GC操作和每次GC執行的時間,并且即使執行GC操作也不會掛起所有工作線程,從而提供并發處理量。
StateServer配置流程
配置WebGarden和WebFarm后,每個請求將由不同的工作進程或應用服務器處理,那么之前保存在工作進程所占內存中的SessionTable和緩存信息將無法共享。最明顯的例子就是通過將用戶的登陸信息保存在SesisonTable中,當啟用WebGarden時,用戶不定時被告知需要重新登陸。這是由于請求被分配到另一個工作進程處理,而該工作進程沒有對應的SessionTable記錄。
這時我們需要配置一臺獨立共享的StateServer來保存Sessoin等信息的服務器。
對于WebGarden:
對于WebFarm:
下面我們一步步配置吧!
1. 服務器配置
1). 安裝ASP.NET State Service組件:控制面板->程序和功能->打開或關閉Windows功能->Internet信息服務->萬維網服務->應用程序開發功能->ASP.NET
2). 在“運行”面板上輸入regedit進入注冊表,進入HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/aspnet_state/Parameters
修改AllowRemoteConnection,用于配置可被遠程鏈接的鏈接數,0表示僅能本機鏈接;
修改Port,用于配置State Service的端口號,一般采用默認42424即可。
3). 啟動/重啟State Service:計算機->管理->服務->ASP.NET State Service 啟用,自動。
2. Web.config配置
配置位于<system.web>下的<sessionState>節點
<!--Session 配置。Session 為請求的當前上下文保存用戶配置,每個用戶獨立。不建議存放大量數據。 mode: Off: 設置為不使用Session功能 InProc: 默認值,在 IIS 進程中保存 Session,無存儲類型、大小限制,性能高,但容易丟失。 StateServer:在 Windows 服務進程中保存 Session,序列化存儲,無大小限制,不依賴 Web 服務器,不容易丟失,但序列化消耗 CPU 性能。 SQLServer:在 SQL Server 中保存 Session,序列化存儲,無大小限制,不依賴 Web 服務器,不容易丟失,但序列化消耗 CPU 性能。 Custom: cookieless: true 使用Cookieless模式;這時客戶端的Session信息就不再使用Cookie存儲了,而是將其通過URL存儲。比如網址為http://localhost/MyTestApplication/(ulqsek45heu3ic2a5zgdl245)/default.aspx false 使用Cookie模式,這是默認值。 timeout 設置經過多少分鐘后服務器自動放棄Session信息。默認為20分鐘。 stateConnectionString 設置將 Session 信息存儲在狀態服務中時使用的服務器名稱和端口號,例如:"tcpip=127.0.0.1:42424”。當mode的值是StateServer是,這個屬性是必需的。(42424是默認端口)。 sqlConnectionString 設置與 SQL Server 連接時的連接字符串。例如 "data source=localhost;Integrated Security=SSPI;Initial Catalog=northwind"。當mode的值是SQLServer時,這個屬性是必需的。 stateNetworkTimeout 設置當使用 StateServer 模式存儲 Session 狀態時,經過多少秒空閑后,斷開Web服務器與存儲狀態信息的服務器的 TCP/IP 連接的。默認值是10秒鐘。--> <sessionState mode="Off|InProc|StateServer|SQLServer" cookieless="true|false" timeout="number of minutes" stateConnectionString="tcpip=server:port" sqlConnectionString="sql connection string" stateNetworkTimeout="number of seconds" />
示例:<sessionState mode="StateServer" stateConnectionString="tcpip=localhost:42424" timeout="2880" />
對于沒有啟用WebFarm而言,上述StateServer配置已經可OK了。但倘若啟用WebFarm,那還要配置以下兩項:
1. 配置MachineKey
machineKey作為加密/解密秘鑰。負載均衡時必須配置,否則會報“無法驗證的錯誤”之類的問題。
默認情況下ASP.NET會自動生成一組machineKey,但作負載均衡時各臺應用服務器所生成的均不同,則會導致無法正確加密解密共享信息。
<machineKey validationKey="86B6275BA31D3D713E41388692FCA68F7D20269411345AA1C17A7386DACC9C46E7CE5F97F556F3CF0A07159659E2706B77731779D2DA4B53BC47BFFD4FD48A54" decryptionKey="9421E53E196BB56DB11B9C25197A2AD470638EFBC604AC74CD29DBBCF79D6046" validation="SHA1" decryption="AES"/>
machineKey的生成函數
生成machineKey: public static string CreateKey(int len) { byte[] bytes = new byte[len]; new RNGCryptoServiceProvider(). GetBytes(bytes); StringBuilder sb = new StringBuilder(); for(int i = 0; i < bytes. Length; i++) { sb. Append(string. Format("{0:X2}",bytes[i])); } return sb. ToString(); } 使用: validationKey = CreateKey(20); decryptionKey = CreateKey(24);
2. 配置AppID
StateServer中Session信息的ID實際上是由AppID和用戶的SessionID組成,因此若部署在多臺應用服務器上的網站的AppID不同,則會導致Session信息丟失的問題。
IIS7下配置AppID
IIS6下配置AppID
方式1:在CMD下輸入 cd c:\Inetpub\AdminScripts
然后輸入 cscript adsutil.vbs move w3svc/999 w3svc/2 意思是將AppID從999改為2。
方式2:修改MetaBase.xml文件。
Q&A
Q:為何我按照上述內容配置WebGarden和StateServer,但偶然間會報如下錯誤呢?
A:由于存放復雜的自定義結構體到SessionTable了,在做反序列化時報錯了。建議只存放String、Int32等簡單類型的數值到SessionTable,然后以它們為鍵再在程序中獲取其它屬性。
總結
上述內容若有紕漏請各位指正,謝謝。
尊重原創,轉載請注明來自: http://www.cnblogs.com/fsjohnhuang/p/5244785.html^_^肥子John
感謝
https://support.microsoft.com/en-gb/kb/932909
http://kb.cnblogs.com/page/122612/
https://blogs.msdn.microsoft.com/httpcontext/2012/06/22/shared-session-state-in-a-iis6-and-iis7-web-farm/
文章列表
留言列表