There can be no Triumph without Loss,No Victory without Suffering,No Freedom without Sacrifice.
All you have to decide is what to do with the time that is given to you.
Get busy Living, or Get busy Dying?
  首页 | 留言给我 | 订阅 Rss | CLI | 黄白之恋 Posts:158   Hits: 5061336    Comments: 173    
 日历归档
<<  <  2024 - 04  >  >>
SuMoTuWeThFrSa
 123456
78910111213
14151617181920
21222324252627
282930
 About Me
 Name: ZhangSichu
 Sex: Male
 Age: 32
 Email: ZhangSichu@gmail.com
 MSN: ZhangSichu@hotmail.com
 Home: ZhangSichu.com
 WeiBo: weibo.com/zhangsichu
 个人推荐
 分类归档
  ·C++/C(5)  RSS
  ·软件工程(1)  RSS
  ·杂事/随感(26)  RSS
  ·.Net/Java(30)  RSS
  ·面向对象程序设计(5)  RSS
  ·汇编/破解(0)  RSS
  ·平面设计(3)  RSS
  ·SQL(5)  RSS
  ·COM/COM+(2)  RSS
  ·Web开发(81)  RSS
 My Friends
Back Forward Refresh Home 2024年4月20日 星期六 RSS CLI Mine Sweeper. In Javascript.

  由Server Too Busy Exception看到的问题
字体大小 [ ]

有一个Asp.Net页面在访问次数增多时,就会产生Server Too Busy Exception。整个站点就被拖累死了,访问哪个页面都是这个错误。奇怪的是访问量小不会出错,访问量一大就会频繁出现这个错误。在出错的时候,打开 Task Manager 看此时的Cpu 占用率和内存的使用情况都比较正常。Cpu没有一直100%被w3wp进程占用。只有20%-30%被占用。内存也剩余了很多。为什么会出这个问题。Google和Baidu都没有找到一个比较合适的答案。只是说要优化,不要频繁使用Server.CreateObject,不去设置IIS的访问个数限制。在这个Asp.Net页面中没有调用Server.CreateObject, IIS也没有设置访问个数。真是不解为什么会出这个错误。

错误如下图:
Click to Open in New Window

又一次重新读了一遍代码。一开始想要解决数据库被频繁查询,在里面加了一个HashTable做为缓存。(这段程序是使用用户的IP从数据库中查询出用户所在的城市)
……
//ipAddr 用户的Ip
long ipAddr = IpToLong(GetUserIp());
if(ipAddr == 0) return null;
if(IpTable[ipAddr] != null) return (string)IpTable[ipAddr]; //IpTable static HashTable 缓存用户ip和城市的对应关系。
string city;
object temp = GetCityFromIp(ipAddr);
city = (temp == null ? "" : temp.ToString());
IpTable.Add(ipAddr, city);
return city;


程序看起来没有什么问题。突然想起来,原来没有加HashTable做缓存,程序可以正常跑,有时候会出现数据库查询错。数据库忙,connection.Open()错。加了HashTable数据库没有错了。出现了ServerTooBusy错。应该是在用HashTable做缓存上错了。反射了HashTable。
发现 public static Hashtable IpTable = new Hashtable(); 会自动创建一个长度为11的bucket数组。bucket是一个struct结构体。

public Hashtable(int capacity, float loadFactor)
{
if (capacity < 0)
{
throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
}
if ((loadFactor < 0.1f) || (loadFactor > 1f))
{
throw new ArgumentOutOfRangeException("loadFactor", Environment.GetResourceString("ArgumentOutOfRange_HashtableLoadFactor", new object[] { 0.1, 1.0 }));
}
this.loadFactor = 0.72f * loadFactor;
double num = ((float) capacity) / this.loadFactor;
if (num > 2147483647.0)
{
throw new ArgumentException(Environment.GetResourceString("Arg_HTCapacityOverflow"));
}
int num2 = (num > 11.0) ? HashHelpers.GetPrime((int) num) : 11;
this.buckets = new bucket[num2];
this.loadsize = (int) (this.loadFactor * num2);
this.isWriterInProgress = false;
}


当调用Add时Add会判断当前HashTable中的数据的个数,如果还有空间就会直接加入,如果没有,会调用rehash。在rehash中会有一个比较消耗空间和时间的深拷贝,就是因为反复调用putEnty,做深拷贝,重新生成HashTable,占用了很多空间和时间。

[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
private void rehash(int newsize)
{
this.occupancy = 0;
Hashtable.bucket[] newBuckets = new Hashtable.bucket[newsize];
for (int i = 0; i < this.buckets.Length; i++)
{
Hashtable.bucket bucket = this.buckets[i];
if ((bucket.key != null) && (bucket.key != this.buckets))
{
this.putEntry(newBuckets, bucket.key, bucket.val, bucket.hash_coll & 0x7fffffff);
}
}
Thread.BeginCriticalRegion();
this.isWriterInProgress = true;
this.buckets = newBuckets;
this.loadsize = (int) (this.loadFactor * newsize);
this.UpdateVersion();
this.isWriterInProgress = false;
Thread.EndCriticalRegion();
}


问题很可能就是在new HashTable时没有指定capacity,当访问量一大,HashTable被多次rehash造成的。
把原来的:public static Hashtable IpTable = new Hashtable();
改成了:  public static Hashtable IpTable = new Hashtable(30000);
问题解决了。

小结:
  估计,类似HashTable这种Collection类型的对象,内部都有这样的处理。反射了NameValueCollection。发现NameValueCollection内部自己保存了一个HashTable和一个Array。ArrayList的Capacity 属性在被Set的时候也会做类似的处理。
  在进行new操作,产生对象的时候,最好预估算一下可能的大小,减少内部做rehash或resize的操作,从而提升性能。或者使用基于链表式的存储对象,在进行添加操作的时候,只操作节点引用,不进行类似resize的操作。.Net 2.0中的SortedDictionary 是一个不错的选择,它内部使用树结构存储数据,实现了类似于红—黑树的数据结构。
  Posted @ 11/12/2007 6:31:59 PM | Hits (35068) | Comments (2

  Comment
 #re:由Server Too Busy Exception看到的问题  3/20/2008 12:57:16 PM  天使相思
我看到很好.
 #re:由Server Too Busy Exception看到的问题  11/29/2007 12:58:13 AM  游客
真诚想和贵博客交换友情链接。
火狐:http://www.huohuliulanqixiazai.com
天天基金:http://www.cnjijin.com
天天基金网:http://www.tiantianjijinwang.com
  Post Comment
标题 *
作者 *
密码 记住我
评论 *
    


Stable in Firefox 1.5 2.0Stable in IE6 IE7Stable in MozillaStable in Netscape
ZhangSichu.com V0.1.7507
Powered By ZhangSichu
Copyright © ZhangSichu
Download ZhangSichu.com source code. Download source code