《Windows 用户态程序高效排错》市场价元 特价元 购买>>
简单的问题最棘手稀疏平常的ASPNET Session Lost问题
问题描述
客户抱怨刚刚开发完成的大型ASPNET站点测试阶段一切正常但是放到生产环境上运行压力一大就会发生Session Lost现象问题的表现是一个NullReferenceException异常分析代码后发现该NullReferenceException是试图访问一个SessionObject时候发生的该SessionObject应该在前面就已经设置过问题半年来一共就发生过次而且是在个不同的页面发生
制定策略
这个问题困难的地方在于重现的几率很小没有多少详细观察的机会所以必须制订非常周全的计划以便问题再次发生的时候获取足够多的信息如何制订周密的计划呢?
思路非常直观了解Session实现的细节总结出导致问题的所有可能性获取信息的时候排查所有的可能性
关于ASPNET Session的细节可以参考
Underpinnings of the Session State Implementation in ASPNET
有了对Session的理解后把这个问题分成了下面几种情况
客户使用了负载均衡的环境但是没有正确配置基于数据库或者服务的Session模式或者是几台服务器的Machine key没有配置成一致跟客户确认后排除了这种情况因为客户只有一个服务器使用的InProc
最简单的情况就是所有的用户所有的session都丢了这种情况一般发生在InProc的session mode上原因就是appdomain重启或者IIS进程崩溃可以通过性能日志或系统日志来排查
稍微麻烦一点的就是某一个用户的session丢了而没有影响到所有用户观察方法是首先在session start里面做log把每一个session的创建时间以及session id都记录到本地的一个log里面同时往session里面添加一个测试用的session value问题发生的时候在ASPNET的全局错误处理函数中当前的session id读出来比较log中的记录看看这个session是不是刚刚建立的如果是很有可能是客户端的原因导致session id丢了比如IE crash导致cookie丢失
如果不是那就看看测试用的session value是不是丢了如果这个也丢了应该是代码中掉了SessionClear
如果测试用的session value没有丢情况就变成一个用户的session里面的一部分value丢了很可能是由于用户的代码逻辑导致的解决方法就是通过更详细的log来定位问题然后阅读代码来检查
可以看到问题的特征跟潜在的根源是对应的目的在于区分出这种情况
所有用户的所有Session全没有了
一个用户的Session没有了
一个用户的部分Session没有了
针对每种情况采取的log策略是
对于第类情况可以在Application_Start/End函数中记录下时间来检查Appdomain是不是重新启动过
对于第类情况log文件应该记录下session id和session创建的时间以便判断问题是否是cookie id lost导致的如果是cookie id lost那问题就出在客户端或者是网络原因
对于第类情况可以在工程中搜索所有Session Clear的调用每次调用前写log文件来记录如果工程很大无法逐一添加可以加载调试器在Session Clear函数中设定条件断点来记录
具体操作和结论
总结下来具体的实现是
在globalasax文件的session_start中把这个session的创建时间记录到session里面这个创建时间也同时充当测试用的session value
代码中对session操作的地方写log到以sessionid为文件名的文件中去
用log文件记录每次session的操作发生在什么函数发生的时间session内容的变化
当Exception发生的时候在Exception handler中记录发生问题的session id和残留下来的Session value
这样问题发生的时候根据Exception handler记录的session id找到log文件就可以很清楚地得到所需要的信息
在做了上述部署之后等了大约一个星期问题重现了在log文件中发现这样的信息
某一个用户的部分Session丢失
从Session创建时间看该Session已经维持很长时间了
通过检查Session Clear的调用纪录发现丢失的Session的确是由用户自己的代码清除的同时发现这些代码的运行次序跟设计不吻合根据设计初衷在清除 Session后页面会重定向到一个专门的页面并重新添加Session然后继续操作但是log表明这个专门的页面并没有得到执行