Httpclient 在服务器开始处理请求之前超时
Httpclient gets a timeout before server starts processing the request
我有一个奇怪的错误,我无法在自己的计算机上重现。
这是我使用的完整代码:
public async Task LoadHeaderAndFooter()
{
//ignore any SSL errors
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
var baseAddress = new Uri(Request.Url.GetComponents(UriComponents.Scheme | UriComponents.Host, UriFormat.Unescaped));
var cookieContainer = new CookieContainer();
using (var handler = new HttpClientHandler { CookieContainer = cookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
var oCookies = Request.Cookies;
for (var j = 0; j < oCookies.Count; j++)
{
var oCookie = oCookies.Get(j);
if (oCookie == null) continue;
var oC = new Cookie
{
Domain = baseAddress.Host,
Name = oCookie.Name,
Path = oCookie.Path,
Secure = oCookie.Secure,
Value = oCookie.Value
};
cookieContainer.Add(oC);
}
Header.Text = await client.GetStringAsync("/minside/loyalityadmin/header");
Footer.Text = await client.GetStringAsync("/minside/loyalityadmin/footer");
}
}
发生的情况是请求开始,然后等待超时(默认 30 sek),httpclient 抛出 "task canceled" 异常。然后实际请求在服务器上触发。
现在这段代码 运行 在 .ascx.cs 文件中。而 /header 是一个带有 .cshtml 视图的 MVC 控件。 运行 在同一台服务器上。
我怎样才能让它工作?
经过更多测试后,似乎 restsharp.org 在某些平台上也有同样的问题(除我的开发平台外的所有地方)。
原来是会话对象的问题。在 IIS 上,无法并行读取会话状态:
Access to ASP.NET session state is exclusive per session, which means
that if two different users make concurrent requests, access to each
separate session is granted concurrently. However, if two concurrent
requests are made for the same session (by using the same SessionID
value), the first request gets exclusive access to the session
information. The second request executes only after the first request
is finished. (The second session can also get access if the exclusive
lock on the information is freed because the first request exceeds the
lock time-out.) If the EnableSessionState value in the @ Page
directive is set to ReadOnly, a request for the read-only session
information does not result in an exclusive lock on the session data.
However, read-only requests for session data might still have to wait
for a lock set by a read-write request for session data to clear.
来自 https://msdn.microsoft.com/en-us/library/ms178581.aspx
所以解决方案就是不传递会话 ID:
if (oCookie == null || oCookie.Name == "ASP.NET_SessionId") continue;
工作正常,因为辅助请求不需要访问会话。感谢任何可以在两个请求中使用会话的解决方案。
我有一个奇怪的错误,我无法在自己的计算机上重现。
这是我使用的完整代码:
public async Task LoadHeaderAndFooter()
{
//ignore any SSL errors
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
var baseAddress = new Uri(Request.Url.GetComponents(UriComponents.Scheme | UriComponents.Host, UriFormat.Unescaped));
var cookieContainer = new CookieContainer();
using (var handler = new HttpClientHandler { CookieContainer = cookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
var oCookies = Request.Cookies;
for (var j = 0; j < oCookies.Count; j++)
{
var oCookie = oCookies.Get(j);
if (oCookie == null) continue;
var oC = new Cookie
{
Domain = baseAddress.Host,
Name = oCookie.Name,
Path = oCookie.Path,
Secure = oCookie.Secure,
Value = oCookie.Value
};
cookieContainer.Add(oC);
}
Header.Text = await client.GetStringAsync("/minside/loyalityadmin/header");
Footer.Text = await client.GetStringAsync("/minside/loyalityadmin/footer");
}
}
发生的情况是请求开始,然后等待超时(默认 30 sek),httpclient 抛出 "task canceled" 异常。然后实际请求在服务器上触发。
现在这段代码 运行 在 .ascx.cs 文件中。而 /header 是一个带有 .cshtml 视图的 MVC 控件。 运行 在同一台服务器上。
我怎样才能让它工作?
经过更多测试后,似乎 restsharp.org 在某些平台上也有同样的问题(除我的开发平台外的所有地方)。
原来是会话对象的问题。在 IIS 上,无法并行读取会话状态:
Access to ASP.NET session state is exclusive per session, which means that if two different users make concurrent requests, access to each separate session is granted concurrently. However, if two concurrent requests are made for the same session (by using the same SessionID value), the first request gets exclusive access to the session information. The second request executes only after the first request is finished. (The second session can also get access if the exclusive lock on the information is freed because the first request exceeds the lock time-out.) If the EnableSessionState value in the @ Page directive is set to ReadOnly, a request for the read-only session information does not result in an exclusive lock on the session data. However, read-only requests for session data might still have to wait for a lock set by a read-write request for session data to clear.
来自 https://msdn.microsoft.com/en-us/library/ms178581.aspx
所以解决方案就是不传递会话 ID:
if (oCookie == null || oCookie.Name == "ASP.NET_SessionId") continue;
工作正常,因为辅助请求不需要访问会话。感谢任何可以在两个请求中使用会话的解决方案。