Singleton httpclient vs创建新的httpclient请求
我想在我的Xamarin.Forms
移动应用程序中使用HttpClient创建web服务层。
- 没有单一模式
- 单身模式
在第一种方法中,我在移动应用程序发出的每个新请求中创建新的http客户端对象。
这是我的代码
public HttpClient GetConnection() { HttpClient httpClient = new HttpClient(); httpClient.BaseAddress = new Uri(baseAddress); httpClient.Timeout = System.TimeSpan.FromMilliseconds(timeout); return httpClient; }
发布请求代码
public async Task PostAsync(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(responseData, _jsonSerializerSettings)); } else { throw new NullReferenceException("NullReferenceException @ PostAsync httpclient is null WebRequest.cs"); } }
客户端将使用以下代码来执行请求
new LoginService(new WebRequest()).UserLogin(userRequest);
实现IWebRequest
内部类
_webRequest.PostAsync(Constants.USER_LOGIN, userRequest);
在第二种方法中,我在这里重新使用每个新请求中的相同http客户端对象,我的单例类也是线程安全的。
private static readonly Lazy lazy = new Lazy(() => 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 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(...)
我通过Web浏览了许多像RestSharp
这样的库只是为了探索最好的,我发现他们中的大多数都在为每个请求创建新对象。 所以我很困惑哪种模式最适合。
Singleton是使用HttpClient
的正确方法。 有关详细信息,请参阅此文章。
Microsoft docs声明:
HttpClient旨在实例化一次,并在应用程序的整个生命周期中重复使用。 为每个请求实例化一个HttpClient类将耗尽重负载下可用的套接字数量。 这将导致SocketException错误。 下面是一个正确使用HttpClient的示例。
事实上,我们在申请中发现了这一点。 我们的代码可能会在foreach
循环中产生数百个API请求,并且对于每次迭代,我们创建了一个包含在using
的HttpClient
。 我们很快就开始从我们的MongoClient
获得红色鲱鱼错误,说它已经超时尝试连接到数据库。 在阅读链接文章后,我们发现即使在处理了HttpClient
,也意识到我们正在耗尽可用的套接字。
唯一需要注意的是, DefaultRequestHeaders
和BaseAddress
类的东西将应用于使用HttpClient的任何地方。 作为单身人士,这可能贯穿整个应用程序。 您仍然可以在应用程序中创建多个HttpClient
实例,但请注意,每次执行时,它们都会创建一个新的连接池,因此应该谨慎创建。
正如hvaughan3所指出的,您也无法更改HttpClient使用的HttpMessageHandler
实例,因此如果这对您很重要,则需要对该处理程序使用单独的实例。
虽然HttpClient
应该被重用,但这并不一定意味着我们必须使用单例来组织我们的代码。 请参考我的答案 。
PS:不确定我是否应该在这里复制并粘贴答案。 让我知道。
正如其他人提到的,大多数HttpClient
应该用作单例,但是有一个例外 – 当你使用HTTP long polling
技术时,你不应该使用HttpClient
作为单例,因为你将阻止其他请求执行。
对于长轮询请求,您应该创建单独的HttpClient
。