.Net魔法堂:开启IIS的WebGarden、WebFarm和StateServer之旅
前言
公司系统虽然配置有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 = ; i < bytes. Length; i++)
{
sb. Append(string. Format("{0:X2}",bytes[i]));
}
return sb. ToString();
} 使用: validationKey = CreateKey();
decryptionKey = CreateKey();
2. 配置AppID
StateServer中Session信息的ID实际上是由AppID和用户的SessionID组成,因此若部署在多台应用服务器上的网站的AppID不同,则会导致Session信息丢失的问题。
IIS7下配置AppID
IIS6下配置AppID
方式1:在CMD下输入 cd c:\Inetpub\AdminScripts
然后输入 cscript adsutil.vbs move w3svc/ w3svc/ 意思是将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/
.Net魔法堂:开启IIS的WebGarden、WebFarm和StateServer之旅的更多相关文章
- 开启IIS的WebGarden、WebFarm和StateServer之旅
前言 公司系统虽然配置有1台NLB后拖4台App Server最后搭一台强劲无比的DB Server,但每天下午4点左右总被投诉系统慢,报表下载不了等问题.究其原因,原来NLB采用锁定sessionI ...
- IIS的WebGarden、WebFarm和StateServer
开启IIS的WebGarden.WebFarm和StateServer之旅 前言 公司系统虽然配置有1台NLB后拖4台App Server最后搭一台强劲无比的DB Server,但每天下午4点左右总被 ...
- HTML5魔法堂:全面理解Drag & Drop API
一.前言 在HTML4的时代,各前端工程师为了实现拖拽功能可说是煞费苦心,初听HTML5的DnD API觉得那些痛苦的日子将一去不复返,但事实又是怎样的呢?下面我们一起来看看DnD API的真面 ...
- CSS魔法堂:hasLayout原来是这样!
前言 过去一直听说旧版本IE下很多诡异bug均由一个神秘角色引起的,那就是hasLayout.趁着最近突然发神经打算好好学习CSS,顺便解答多年来的疑惑. hasLayout到底是何方神圣? hasL ...
- JS魔法堂:浏览器模式和文档模式怎么玩?
一.前言 从IE8开始引入了文档兼容模式的概念,作为开发人员的我们可以在开发人员工具中通过“浏览器模式”和“文档模式”(IE11开始改为“浏览器模式”改成更贴切的“用户代理字符串”)品味一番,它的出现 ...
- JS魔法堂:不完全国际化&本地化手册 之 理論篇
前言 最近加入到新项目组负责前端技术预研和选型,其中涉及到一个熟悉又陌生的需求--国际化&本地化.熟悉的是之前的项目也玩过,陌生的是之前的实现仅仅停留在"有"的阶段而已. ...
- JS魔法堂:不完全国际化&本地化手册 之 实战篇
前言 最近加入到新项目组负责前端技术预研和选型,其中涉及到一个熟悉又陌生的需求--国际化&本地化.熟悉的是之前的项目也玩过,陌生的是之前的实现仅仅停留在"有"的阶段而已. ...
- WebComponent魔法堂:深究Custom Element 之 标准构建
前言 通过<WebComponent魔法堂:深究Custom Element 之 面向痛点编程>,我们明白到其实Custom Element并不是什么新东西,我们甚至可以在IE5.5上定 ...
- WebComponent魔法堂:深究Custom Element 之 面向痛点编程
前言 最近加入到新项目组负责前端技术预研和选型,一直偏向于以Polymer为代表的WebComponent技术线,于是查阅各类资料想说服老大向这方面靠,最后得到的结果是:"资料99%是英语 ...
随机推荐
- nginx+winsw windows服务
1.下载Nginx:http://nginx.org/en/download.html 2.下载winsw配置包:http://files.cnblogs.com/files/objecttozero ...
- 创建寄宿在Windows服务中的WCF服务
1.创建Windows服务项目 2.Server1改名为你想要的名称,比如WinServer 3.在项目中新建一个WCF文件夹,用于存放wcf服务文件. 注:在WcfServer类的上面还要添加 [S ...
- RCP:eclipse的DEBUG机制
Eclipse debug文档翻译 运行一个程序需要添加launch configurable,在自定义launch configuration的时候会指定模式,比如run,debug,profile ...
- 谈谈final的作用
前言 一直想写写这个话题.代表公司也面试过一些求职者,每次面试我必问的两个问题之一就是“请你谈一谈对于final关键字的理解”.这是一个简单的小问题,但是不要小看它,通过对这个问题的回答以及一些简单的 ...
- [分享黑科技]纯js突破localstorage存储上线,远程抓取图片,并转码base64保存本地,最终实现整个网站所有静态资源离线到用户手机效果却不依赖浏览器的缓存机制,单页应用最新黑科技
好久没有写博客了,想到2年前答应要放出源代码的也没放出来,最近终于有空先把纯js实现无限空间大小的本地存储的功能开源了,项目地址https://github.com/xueduany/localsto ...
- Linux用户切换
1,查看当前user: whoami 2,普通用户切换到root,会要求输入密码: su 3,root切换到普通用户: su - username
- 解析for循环
循环的作用就是让一个程序.连续进行一遍又一遍的循环: for循环: 分为四大类: 初始状态:相当于他一开始的数值,或条件: 循环条件:满足进行循环,不满足则停止: 循环体:循环的东西,程序: 状态改变 ...
- Struts2学习笔记 - Action篇<配置文件中使用通配符>
有三种方法可以使一个Action处理多个请求 动态方法调用DMI 定义逻辑Acton 在配置文件中使用通配符 这里就说一下在配置文件中使用通配符,这里的关键就是struts.xml配置文件,在最简单的 ...
- android 权限大全
教程 博客 淘帖 论坛›eoe·Android开发资源区›Android开发实例教程 191507 12 / 2 页下一页 android 权限大全 『癲瘋霸気』 于 2013-4-3 10: ...
- Unity3D Editor模式下批量修改prefab
最经遇到一个需要批量修改已经做好的prefab的问题,查了一些资料最终实现了但是还是不够完美,通过学习也发现unity的编辑器功能还是非常强大的.废话不多说直接上代码: [ExecuteInEditM ...