摘要:asp.netcore 高并發下使用HttpClient的方法
大家都知道,使用HttpClient,在并發量不大的情況,一般沒有任何問題;但是在并發量一上去,如果使用不當,會造成很嚴重的堵塞的情況。
解決方案如下:
一、可以參考微軟官方提供的方法:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/http-requests?view=aspnetcore-2.2
二、我的解決方案是根據官方提供的方法,選擇一種最适合項目的寫法進行改造。
1、nuget添加包Microsoft.AspNetCore.Http;
2、startup裡ConfigureServices方法添加代碼:
//添加httpclient方法
services.AddHttpClient("ApiServiceName", c =>
{
c.BaseAddress = new Uri(Configuration["ApiConfig:SystemService"]);//位址從配置檔案appsettings.json裡取
c.Timeout = TimeSpan.FromSeconds(30);//逾時間時間設定為30秒
3、在需要用的地方注入進去:(一般在構造函數裡)
private ILogger logHelper;
private readonly IHttpContextAccessor httpContextAccessor;
private readonly IHttpClientFactory _clientFactory;
HttpClient client;
public articleService(ILogger<reportService> logger, IHttpContextAccessor _httpContextAccessor, IHttpClientFactory clientFactory)
{
logHelper = logger;
httpContextAccessor = _httpContextAccessor;
_clientFactory = clientFactory;
client = _clientFactory.CreateClient("ApiServiceName");
}
client = _clientFactory.CreateClient("SystemService"); 這句話也可以在具體的方法裡執行,因為我們的項目全部都是調用接口,是以放構造函數比較省事。
4、添加一個公共方法:
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace MuXue.Common
{
/// <summary>
/// 異步調用,并且client是注入方式,傳過來
/// 2019-8-21
/// 李樸
/// </summary>
public class MyHttpClientHelper
{
public async Task<T> GetData<T>(HttpClient client, GateWay action, dynamic param)
{
string paramStr = JsonConvert.SerializeObject(param);
string jrclientguid = Guid.NewGuid().ToString("n");
try
{
LogHelper.Info($"MyHttpClientHelper開始,url={client.BaseAddress},action={Utils.GetEnumDescription(action)},postData={paramStr} ,jrclientguid={jrclientguid}---------");
client.DefaultRequestHeaders.Add(CommonConstant.jrclientguid, jrclientguid);
HttpResponseMessage response;
using (HttpContent httpContent = new StringContent(paramStr, Encoding.UTF8))
{
httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
response = await client.PostAsync("api/" + Utils.GetEnumDescription(action), httpContent);
}
if (response != null && response.IsSuccessStatusCode)
{
T resp = await response.Content.ReadAsAsync<T>();
return resp;
}
else
{
return default(T);
}
}
catch (Exception ex)
{
throw;
}
finally
{
LogHelper.Info($"MyHttpClientHelper結束,url={client.BaseAddress},action={Utils.GetEnumDescription(action)},postData={paramStr} ,jrclientguid={jrclientguid}---------");
}
}
}
}
這裡的參數 GateWay action 也可以換做是接口位址(不包含域名);
5、接着在第3步的那個類裡,需要調用接口的地方寫方法:
//2、取接口裡取
MyHttpClientHelper myHttpClientHelper = new MyHttpClientHelper();
Result<List<Article>> resp=await myHttpClientHelper.GetData<Result<List<Article>>>(client, GateWay.GetNoticeList, null);
這樣就完成了。
6、全部用異步方式;