子非鱼,安知鱼之乐?

我的程序人生,累并快乐着。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Asp.net 2.0的问题真要了命了

Posted on 2006-09-12 13:49  Jason Cui  阅读(2616)  评论(13编辑  收藏  举报
升级以后遇到的问题前所未见。
日志里面出现了一堆的错误和提示,提示是用户提供的验证票据不合法。这个我明白,因为1.1的时候用户使用的Cookie的算法跟2.0不一样,所以认为用户提供非法Cookie,这个可以忽略。错误是未处理的异常,值不能为空。这个错误的详细信息千奇百怪,出现的页面信息很随机,但是我找来找去也没发现有什么未处理的异常了。后来还发现有一个用户一直向服务器提供非法数据,而服务器在使用传回的数据之前没有做太多检查,比如数字就直接用int.Parse了。这里造成了异常。但是这里的整段程序的调用都是在一个Try块里面执行的,不应该有这个问题啊。
最严重的一个问题,是w3wp.exe会突然重启,日志记录是ISAPI检测到死锁。后来无论如何也找不到死锁的来源。而且现在一旦进程重启,系统会重新编译,尽管我已经用aspnet_compiler.exe完全编译过了也没有用。更甚者,现在的编译时间极其缓慢。看了一下日志,编译上几分钟就会再一次出现死锁的错误,所以又被重启了一次,又编译。
查了N多网站,发现死锁不仅仅是对文件资源的访问,对CPU也会造成这个问题,由于访问量大,连接进来的进程多,每个进程启动一个csc.exe,将所有的CPU都占满了,再进来的进程就会一直等待,而原来的进程又很难返回。于是系统自作聪明的把现在正在编译的这个w3wp.exe给重启了一下,却不知,等待资源的和抢占资源的不是别人,而是它自己。于是整个网站陷入这个死循环。
于是立下狠心,将IIS的默认站点停掉,启动aspnet_compiler来编译网站,1分钟以后编译完成,启动网站,顺利启动了,不再执行csc.exe的编译过程。
折腾了好几天,总结出一点东西,要更新网站,至少需要这几步:
1、在IIS里同时存在两个完全相同的网站,一个用来正常服务,一个用来更新。根据主机头来区分。
2、更新之前,保证对外服务的那个目前是完全正常的,而用来更新的那个,要保证没有人会访问到它。
3、更新这个内部的网站,启用aspnet_compiler完全编译它。
4、自己测试这个内部网站,多点几个页面,确保它不会启动csc.exe来编译。
5、切换两个站点的主机头,更新它们的位置。这一步动作快一点就行了,我还没找到有什么脚本的方法来做这个。或者先将对外的那个主机头换成www,把另一个改成没有主机头,再把www的那个改成其它。这样就不会有任何问题了
这样子用户基本上不会感觉到停顿,而且不至于让整个站点陷入编译的恶性循环。
上次很多人问aspnet_compiler的具体用法,简单说明一下:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_compiler -m /LM/W3SVC/534451290/ROOT -c
-m是指明根据站点路径来编译,它会自动根据这个找到站点的文件,多站点时编译必须。如果只有一个站点根据虚拟目录来区分,使用-v和-p两个参数。后面的路径中间那一段数字可以在IIS的管理界面中看到,默认站点就是1。-c表明要执行重新生成,否则增量编译。
这个过程是就地编译,将编译结果直接放入.Net缓存目录。所以就不再需要csc.exe编译的那一步了。

PS 服务器环境:至强3.4G*2,双核,4G内存(实际可见3.5G),硬盘72×3 RAID5。