使用WebRequest 在Web后台发送请求,给request设定proxy,发现在特定账号下运行,调用WebRequest.GetSystemWebProxy(),会出现严重的效能问题。
var request = (HttpWebRequest)WebRequest.Create(new Uri(url)); request.Method = isPost ? "POST" : "GET"; request.UserAgent = _userAgent; Stopwatch sw = new Stopwatch(); sw.Start(); request.Proxy = WebRequest.DefaultWebProxy; var total1 = sw.ElapsedMilliseconds.ToString(); sw.Restart(); // 特定账号如ApplicationPoolIdentity下,调用此方法非常耗时,2~3s左右 request.Proxy = WebRequest.GetSystemWebProxy(); sw.Stop(); var total2 = sw.ElapsedMilliseconds.ToString(); bool isBypassed = request.Proxy.IsBypassed(request.RequestUri);
使用asp.net development server 或者直接单元测试的时候,因为进程的运行账号是当前NT账号,属于administrator,不会发现问题。
但是如果发不成站点运行,而站点的应用程序池使用的运行账号是ApplicationPoolIdentity, 则会出现严重的效能问题,Web服务器端每发一个http请求,都需要3s多。
通过Debug发现问题出在WebRequest.GetSystemWebProxy()的调用上,猜测原因可能是,ApplicationPoolIdentity的权限比较低,调用GetSystemWebProxy()需要切换安全上下文,导致出现效能问题。
经过测试,将应用程序池使用的运行账号设置为ApplicationPoolIdentity,LocalService, NetworkService都会出现此问题。设置整LocalSystem则不会。
另外,在不同的账号下运行,调用etSystemWebProxy()获取到的对象也是不一样的,和当前的账号相关。以NT账号运行时候,得到的和IE里面设置的一致,其他的则不尽相同。
解决办法
1. 将应用程序池的运行账号设置为LocalSystem
或者
2. 通过WebRequest.DefaultWebProxy设置request.Proxy.