gpt4 book ai didi

c# - 单例 httpclient 与创建新的 httpclient 请求

转载 作者:IT王子 更新时间:2023-10-29 04:42:43 27 4
gpt4 key购买 nike

我正在尝试在我的 Xamarin.Forms 移动应用程序中使用 HttpClient 创建网络服务层。

  1. 没有单例模式
  2. 单例模式

第一种方法中,我在每个新请求中创建新的 http 客户端对象通过移动应用程序。

这是我的代码

  public HttpClient GetConnection()
{

HttpClient httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(baseAddress);
httpClient.Timeout = System.TimeSpan.FromMilliseconds(timeout);


return httpClient;

}

发布请求代码

 public async Task<TResult> PostAsync<TRequest, TResult>(String url, TRequest requestData)
{
HttpClient client = GetConnection();
String responseData = null;
if (client != null)
{

String serializedObject = await Task.Run(() => JsonConvert.SerializeObject(requestData, _jsonSerializerSettings));
var jsonContent = new StringContent(serializedObject, System.Text.Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync(new Uri(url, UriKind.Relative), jsonContent);
responseData = await HandleResponse(response);


return await Task.Run(() => JsonConvert.DeserializeObject<TResult>(responseData, _jsonSerializerSettings));


}
else
{

throw new NullReferenceException("NullReferenceException @ PostAsync httpclient is null WebRequest.cs");

}

}

客户端会使用下面的代码来执行请求

new LoginService(new WebRequest()).UserLogin(userRequest);

实现 IWebRequest 的内部类

_webRequest.PostAsync<UserRequest,bool>(Constants.USER_LOGIN, userRequest);

第二种方法中,我在每个新请求中重复使用相同的 http 客户端对象在这里,我的单例类也是线程安全的。

private static readonly Lazy<HttpService> lazy =
new Lazy<HttpService>(() => new HttpService());

public static HttpService Instance { get { return lazy.Value; } }



private HttpClient getConnection()
{

client = new HttpClient();
client.Timeout = System.TimeSpan.FromMilliseconds(timeout);

//client.MaxResponseContentBufferSize = 500000;
client.BaseAddress = new Uri(baseAddress);
return client;
}

发布请求代码

public Task<HttpResponseMessage> sendData(String url,String jsonData)
{

var jsonContent = new StringContent(jsonData, System.Text.Encoding.UTF8, "application/json");

return getConnection().PostAsync(new Uri(url, UriKind.Relative), jsonContent);
}

客户端会使用下面的代码来执行

HttpService.Instance.sendData(...)

我已经通过网络浏览了很多库,比如 RestSharp,只是为了探索最好的,我发现它们中的大多数都在根据请求创建新对象。所以我很困惑哪种模式最合适。

最佳答案

更新:似乎使用HttpClient 的单个静态实例doesn't respect DNS changes ,所以解决方案是使用 HttpClientFactory。参见 here有关它的 Microsoft 文档。

要使用 HttpClientFactory,您必须使用 Microsoft 的依赖注入(inject)。这是 ASP.NET Core 项目的默认设置,但对于其他项目,您必须引用 Microsoft.Extensions.HttpMicrosoft.Extensions.DependencyInjection

然后当您创建服务容器时,您只需调用 AddHttpClient():

var services = new ServiceCollection();
services.AddHttpClient()
var serviceProvider = services.BuildServiceProvider();

然后您可以将 IHttpClientFactory 注入(inject)到您的服务中,在后台 HttpClientFactory 将维护一个 HttpClientHandler 对象池 - 保持您的 DNS connection pool exhaustion 的新鲜和预防问题.


旧答案:

Singleton 是使用 HttpClient 的正确方法。请看this有关详细信息的文章。

微软 docs状态:

HttpClient is intended to be instantiated once and re-used throughout the life of an application. Instantiating an HttpClient class for every request will exhaust the number of sockets available under heavy loads. This will result in SocketException errors. Below is an example using HttpClient correctly.

事实上,我们在我们的应用程序中发现了这一点。我们有可能在 foreach 循环中发出数百个 API 请求的代码,并且对于每次迭代,我们都创建了一个 HttpClient 包裹在 using 中.我们很快就开始从我们的 MongoClient 中收到红色鲱鱼错误,说它尝试连接到数据库时已超时。阅读链接的文章后,我们发现即使在处理完 HttpClient 之后,我们也意识到我们正在用尽可用的套接字。

唯一需要注意的是,DefaultRequestHeadersBaseAddress 之类的东西将应用于任何使用 HttpClient 的地方。作为单例,这可能贯穿整个应用程序。您仍然可以在您的应用程序中创建多个 HttpClient 实例,但请注意,每次您这样做时,它们都会创建一个新的连接池,因此应该谨慎创建。

正如 hvaughan3 所指出的,您也无法更改 HttpClient 使用的 HttpMessageHandler 的实例,因此如果这对您很重要,您将需要对该处理程序使用单独的实例。

关于c# - 单例 httpclient 与创建新的 httpclient 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48778580/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com