WebClient.DownloadString() +休息+ HTTPS + Win2003 = 挂起线程
我已经与这个问题斗争了两个多星期了,但毫无进展。
首先环境:Windows 2003 R2 SP2 / SharePoint 2007 SP1 / .NET 3.5。
基本上,我们正在调用 Web 服务来从远程 API 收集数据。该 API 有多个 REST 端点和多个 SOAP 端点。端点是具有摘要身份验证的 HTTPS 端点。当我们使用 SOAP 端点进行调用时,一切似乎都工作正常。但随后我们尝试使用 REST 进行调用,当 IIS 确定该线程不再响应并杀死它时,该线程挂起,然后可怕地死亡。起初,我们认为这是一个 SSL 问题(现在仍然可能是),因为我们在使用 HTTP 端点时没有看到任何问题(路由到相同的 API,只是不是 SSL)。
下面是我们用来进行 REST 调用的代码:
private void Process(HttpContext context, String url, String restParam)
{
ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(validateCertificate);
WriteLogMessage("Start Process");
String pattern = "{0}{1}";
String address = String.Format(pattern, url, restParam);
WriteLogMessage("ADDRESS is" + address);
LSWebClient client = new LSWebClient();
client.Timeout = 600000;
WriteLogMessage("TIMEOUT (client.Timeout) is " + client.Timeout.ToString());
client.Credentials = new NetworkCredential(XYZConfigurationSettings.APIUserName, XYZConfigurationSettings.APIPassword);
try {
String result = client.DownloadString(address);
WriteLogMessage("End Process. RESULT length is " + (result != null ? result.Length : 0));
context.Response.Write(result);
}
catch (Exception ex)
{
WriteLogMessage("EXCEPTION!!! Message----" + ex.Message + "---- StackTrace ----" + ex.StackTrace + "");
}
}
private bool validateCertificate(object sender, X509Certificate cert, X509Chain chain, System.Net.Security.SslPolicyErrors error)
{
WriteLogMessage("bypassAllCertificateStuff");
return true;
}
因此,除了蹩脚的代码之外,我们在这里添加了一些内容来尝试解决我们认为的 SSL 证书问题。 (将请求超时设置为 10 分钟,使用自定义证书验证等...)但是,这些似乎都不能解决问题。
这是我们的日志记录结果:
2/28/2011 3:35:28 PM: Start
2/28/2011 3:35:28 PM: Start Process
2/28/2011 3:35:28 PM: ADDRESS ishttps://<host>/ws/rs/v1/taxonomy/TA/root/
2/28/2011 3:35:28 PM: TIMEOUT (client.Timeout) is 600000
2/28/2011 3:35:50 PM: CheckValidationResult
2/28/2011 3:35:50 PM: bypassAllCertificateStuff
2/28/2011 3:41:51 PM: EXCEPTION!!! Message ----Thread was being aborted.---- StackTrace ---- at System.Net.Connection.CompleteStartConnection(Boolean async, HttpWebRequest httpWebRequest)
at System.Net.Connection.CompleteStartRequest(Boolean onSubmitThread, HttpWebRequest request, TriState needReConnect)
at System.Net.Connection.SubmitRequest(HttpWebRequest request)
at System.Net.ServicePoint.SubmitRequest(HttpWebRequest request, String connName)
at System.Net.HttpWebRequest.SubmitRequest(ServicePoint servicePoint)
at System.Net.HttpWebRequest.GetResponse()
at System.Net.WebClient.GetWebResponse(WebRequest request)
at System.Net.WebClient.DownloadBits(WebRequest request, Stream writeStream, CompletionDelegate completionDelegate, AsyncOperation asyncOp)
at System.Net.WebClient.DownloadDataInternal(Uri address, WebRequest& request)
at System.Net.WebClient.DownloadString(Uri address)
at System.Net.WebClient.DownloadString(String address)
at XYZ.DAO.Handlers.RestServiceHandler.Process(HttpContext context, String url, String restParam)
at XYZ.DAO.Handlers.RestServiceHandler.ProcessRequest(HttpContext context)----
我尝试使用浏览器查看返回数据,但浏览器是IE6,不支持SSL。但是,我可以看到(在 Fiddler / Charles 代理中)它确实尝试发出请求并收到 401 错误,但由于我看不到使用这些程序的服务器流量,我无法准确判断错误发生在哪一步。
更糟糕的是,我无法在我拥有的任何其他服务器上重现此问题(注意:它们都是 Windows 2008 服务器)。
所以,总而言之,这就是我的发现:
SOAP - 工作
休息 - 不工作
Win2008 - 工作
Win2003 - 无法工作
HTTP - 工作
HTTPS - 不起作用
如果有人有任何见解或任何其他我没有尝试过的调试/信息收集,我将非常感激。
I've been battling with this issue for over 2 weeks now and have gotten nowhere.
First the environment: Windows 2003 R2 SP2 / SharePoint 2007 SP1 / .NET 3.5.
Basically, we are making web service calls to gather data from a remote API. The API has several endpoints for REST and several for SOAP. The endpoints are HTTPS endpoints with digest authentication. When we make calls with the SOAP endpoints, everything seems to work just fine. But then we try to make a call using REST and the thread hangs then dies a horrible death when IIS decides that the thread isn't responding anymore and kills it. At first, we thought this was an SSL issue (and it still might be) because we don't see any issues when using the HTTP endpoints (route to the same API just not SSL).
Below is the code we're using to make the REST call:
private void Process(HttpContext context, String url, String restParam)
{
ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(validateCertificate);
WriteLogMessage("Start Process");
String pattern = "{0}{1}";
String address = String.Format(pattern, url, restParam);
WriteLogMessage("ADDRESS is" + address);
LSWebClient client = new LSWebClient();
client.Timeout = 600000;
WriteLogMessage("TIMEOUT (client.Timeout) is " + client.Timeout.ToString());
client.Credentials = new NetworkCredential(XYZConfigurationSettings.APIUserName, XYZConfigurationSettings.APIPassword);
try {
String result = client.DownloadString(address);
WriteLogMessage("End Process. RESULT length is " + (result != null ? result.Length : 0));
context.Response.Write(result);
}
catch (Exception ex)
{
WriteLogMessage("EXCEPTION!!! Message----" + ex.Message + "---- StackTrace ----" + ex.StackTrace + "");
}
}
private bool validateCertificate(object sender, X509Certificate cert, X509Chain chain, System.Net.Security.SslPolicyErrors error)
{
WriteLogMessage("bypassAllCertificateStuff");
return true;
}
So, crappy code aside, we put in a few things here to try to get around what we thought was an SSL Certificate issue. (setting the request timeout to 10 minutes, using custom certificate validation, etc...) However, none of this seems to fix the issue.
Here's the result of our logging:
2/28/2011 3:35:28 PM: Start
2/28/2011 3:35:28 PM: Start Process
2/28/2011 3:35:28 PM: ADDRESS ishttps://<host>/ws/rs/v1/taxonomy/TA/root/
2/28/2011 3:35:28 PM: TIMEOUT (client.Timeout) is 600000
2/28/2011 3:35:50 PM: CheckValidationResult
2/28/2011 3:35:50 PM: bypassAllCertificateStuff
2/28/2011 3:41:51 PM: EXCEPTION!!! Message ----Thread was being aborted.---- StackTrace ---- at System.Net.Connection.CompleteStartConnection(Boolean async, HttpWebRequest httpWebRequest)
at System.Net.Connection.CompleteStartRequest(Boolean onSubmitThread, HttpWebRequest request, TriState needReConnect)
at System.Net.Connection.SubmitRequest(HttpWebRequest request)
at System.Net.ServicePoint.SubmitRequest(HttpWebRequest request, String connName)
at System.Net.HttpWebRequest.SubmitRequest(ServicePoint servicePoint)
at System.Net.HttpWebRequest.GetResponse()
at System.Net.WebClient.GetWebResponse(WebRequest request)
at System.Net.WebClient.DownloadBits(WebRequest request, Stream writeStream, CompletionDelegate completionDelegate, AsyncOperation asyncOp)
at System.Net.WebClient.DownloadDataInternal(Uri address, WebRequest& request)
at System.Net.WebClient.DownloadString(Uri address)
at System.Net.WebClient.DownloadString(String address)
at XYZ.DAO.Handlers.RestServiceHandler.Process(HttpContext context, String url, String restParam)
at XYZ.DAO.Handlers.RestServiceHandler.ProcessRequest(HttpContext context)----
I have attempted to use my browser to view the return data, but the browser is IE6, which doesn't support SSL. However, I can see (in Fiddler / Charles proxy) that it does attempt to make the request and receives a 401 error but since I can not see server traffic using these programs I can not tell at exactly what step the error is happening.
To make matters worse, I can not reproduce this issue on any other server I have (note: they are all Windows 2008 servers).
So, in summary, here's what I've found:
SOAP - work
REST - no work
Win2008 - work
Win2003 - no work
HTTP - work
HTTPS - no work
If anyone has any insight or any other debugging / information gathering that I haven't tried I would be extremely greatful.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果将以下内容添加到客户端 .config 文件中,您应该能够获得更多跟踪信息。
You should be able to get a bunch more tracing information if you add the following to your client .config file.
我发现了导致 Web 服务调用挂起的原因 - 问题是我们调用的服务正在使用重播攻击保护和摘要安全性:
请求没有安全标头
标准 401 挑战提供了
供使用的随机数。 (该随机数过期
10秒后
挑战)
使用生成第二个响应
这个随机数
过期的随机数再次发出
另一个401挑战。
该循环将继续,直到本地服务器的线程终止。然而,为什么我们的本地服务器要花费 30 $@#%!生成安全标头的秒数超出了我的能力范围。我检查了通过上述诊断提供的日志,但没有多大帮助。我将其归咎于服务器超载,并且没有足够的内存来处理湿纸袋中的数据。
I've found what was causing the web service call to hang - the issue was that the service we were calling was using replay attack protection along with digest security:
request sans security header
standard 401 challenge providing a
nonce for use. (That nonce expires
after 10 seconds after the
challenge)
generate a second response using
this nonce
expired nonce and again issue
another 401 challenge.
The cycle would continue until the local server's thread was terminated. However, why our local server is taking 30 $@#%! seconds to generate a security header is beyond me. I inspected the logs that were provided through the diagnostics above, but none of it was much help. I'm going to chalk it up to the server being overloaded and not having enough memory to process it's way out of a wet paper bag.