使用.net core开发,视图页数据通过HttpClient调用core WebApi的接口,但是时常出现站点(部署在IIS)打开缓慢或者打不开的情况。此时查看任务管理器,发现该站点的线程数增长到好几百了,此时把该进程结束掉,站点就回复正常了,请问各位是哪里出现了问题,怎样解决排查?
如图所示:73是该站点在任务管理器中的线程数,此时正常,如果到三五百站点就挂了。
把声明 HttpClient
的地方改为 static
试试
wo看过你先前写的关于HTTPClient的文章,
这是我参考写的
private static HttpClient client;
static HttpHelper() {
client = new HttpClient();
}
public async Task<string> GetRequest(string url, string token = "")
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
if (!string.IsNullOrEmpty(token))//需要登录
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
}
HttpResponseMessage msg = await client.GetAsync(url);
HttpStatusCode statusCode = msg.StatusCode;
var result = await msg.Content.ReadAsStringAsync().ConfigureAwait(false);
return result;
}
然后报错:HTTP Error 400. The size of the request headers is too long.
如果我每次实例化HTTPClient的时候就没这个错误。Token是JWT生成的,长度确实非常大。
client.DefaultRequestHeaders.Clear();
是不是每次请求前都需要清空一下请求头,要不然会重复发送请求头
@Impossible: 可以使用 HttpRequestMessage ,示例代码如下:
class Program
{
private static readonly HttpClient _httpClient = new HttpClient();
static async Task Main(string[] args)
{
var result = await GetRequest("https://q.cnblogs.com");
Console.WriteLine(result);
}
public static async Task<string> GetRequest(string url, string token = "")
{
var request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
if (!string.IsNullOrEmpty(token))
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
}
var response = await _httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
}
}
@dudu: 已经改成静态HTTPClient的形式了,但是线程数还是一直向上涨。但是程序中除了使用async Task的形式外,没有直接涉及到使用线程的地方,貌似很难找到症结
@Impossible: 有没有地方在同步方法中调用异步方法
@dudu: 有,有几个方法中没有用await,直接调用异步方法后使用Result获取值了。
@Impossible: 这就是罪魁祸首,参考 .NET Core中遇到奇怪的线程死锁问题:内存与线程数不停地增长
@dudu: 经过这今天观察,在某个时候还是会出现线程不停的增长,内存正常。所有的有同步方法调用异步的地方,HttpClient也改为静态的了。在视图中有一部分调用异步方法的代码,有没有可能是这一部分引起的?
@if (ViewContext.HttpContext.User.Identity.IsAuthenticated) { string token = ViewContext.HttpContext.User.Claims.FirstOrDefault(x => x.Type == System.Security.Claims.ClaimTypes.Name).Value; MemberService service = new MemberService(token); Member m = await service.GetMember(); }
@Impossible: 所有调用异步方法的同步
方法都要改为异步
的,可以看看这个博问: https://q.cnblogs.com/q/106342/
@dudu: 最近在使用HttpClient的时候发现了另一个问题:Error while copying content to a stream。定位是var response = await _httpClient.SendAsync(request);抛出的异常。我没有使用response.EnsureSuccessStatusCode();,我这里有时还要用401和409的状态码。
我知道,一定是代码中有什么问题才引起的。
很明显有线程任务没有结束。
如果都不太熟.net core—— 那.net core有什么优势呢,为什么选.net core,何况乎还部署iis。
下有tcpListner,http Listner作为选择,上有wcf,asp.net族。
像web api,除非某些特定情况,一般不选择iis,更多是前三者,具体看情况。比如较复杂的关系业务类的,http Listner实现,过去盒子资源极度不足的且那会儿mono类库支持等问题使用tcp Listner,简单业务如单向游戏类的可能选择wcf,asp.net解决web api的话顶多现成asp.net项目需要开接口。
.net core更多的是个忽悠的噱头概念。比如从tcp、http写难道不能跨平台,iis本来都还相当于看门狗(或者专业点叫守护进程)[定时重启],能搞死只能是代码太烂——比如这种情况,情况通常有下:1,任务时间本身很长,2,循环死,3,面条线程死,4,递归调用死(类似第3条)。
进程dump一个下来,vs打开,分分钟那个就找到了原因了。
首先HttpClient应该是被注入Instance, 每次调用的时候设置从 HttpContextAccessor中获取 token(参考eShopOnContainers),
恰好遇到过这种问题,我的是因为部署在linux下,nginx header过长(不只是token,还有cookie)被截断导致的,治标的方法是去研究nginx的配置,治本的方式是在AddCookie(options => options.SessionStore 改成 CookieSessionStore),如果是分布式部署(多授权中心)方式,需要把CookieSessionStore的存储方式改成 Redis方式
AddCookie中看到有 options.SessionStore,没CookieSessionStore,是要自己实现还是在某个命名空间中?
@Impossible: 自己根据实际情况实现
@Impossible: 解决了吗?解决了可以结帖啊,100分啊