2020-10-31

.net的 http 请求 利用单例减少创建销毁的资源开销 提高利用率

参照腾讯云sdk  链接  https://github.com/TencentCloud/tencentcloud-sdk-dotnet/blob/master/TencentCloud/Common/Http/HttpConnection.cs

减小创建的开销可以用单例,也可以用请求池,后续再简单写个请求池,这次主要贴下腾讯的代码,照着腾讯sdk的请求方式 可以直接搬到自己的项目中去使用 代码就不一一解释了,很容易看明白

using System;using System.Collections.Concurrent;using System.Collections.Generic;using System.Net;using System.Net.Http;using System.Net.Http.Headers;using System.Text;using System.Threading.Tasks;namespace TencentCloud.Common.Http{ public class HttpConnection {  private class HttpClientHolder  {   private static readonly ConcurrentDictionary<string, HttpClientHolder> httpclients = new ConcurrentDictionary<string, HttpClientHolder>();   public static HttpClient GetClient(string proxy)   {    string key = string.IsNullOrEmpty(proxy) ? "" : proxy;    HttpClientHolder result = httpclients.GetOrAdd(key, (k) =>    {     return new HttpClientHolder(k);    });    TimeSpan timeSpan = DateTime.Now - result.createTime;    // 每5分钟创建一个新的连接,放弃旧连接,避免DNS刷新问题。    while (timeSpan.TotalSeconds > 300)    {     ICollection<KeyValuePair<string, HttpClientHolder>> kv = httpclients;     kv.Remove(new KeyValuePair<string, HttpClientHolder>(key, result));     result = httpclients.GetOrAdd(key, (k) =>     {      return new HttpClientHolder(k);     });     timeSpan = DateTime.Now - result.createTime;    }    return result.client;   }   public readonly HttpClient client;   public readonly DateTime createTime;   public HttpClientHolder(string proxy)   {    string p = string.IsNullOrEmpty(proxy) ? "" : proxy;    if (p == "")    {     this.client = new HttpClient();    }    else    {     var httpClientHandler = new HttpClientHandler     {      Proxy = new WebProxy(proxy),     };     this.client = new HttpClient(handler: httpClientHandler, disposeHandler: true);    }    this.client.Timeout = TimeSpan.FromSeconds(60);    this.createTime = DateTime.Now;   }  }  private readonly HttpClient http;  private readonly string baseUrl;  private readonly string proxy;  private readonly int timeout;  public HttpConnection(string baseUrl, int timeout, string proxy, HttpClient http)  {   this.proxy = string.IsNullOrEmpty(proxy) ? "" : proxy;   this.timeout = timeout;   this.baseUrl = baseUrl;   if (http != null)   {    this.http = http;   }   else   {    this.http = HttpClientHolder.GetClient(this.proxy);   }  }  private static string AppendQuery(StringBuilder builder, Dictionary<string, string> param)  {   foreach (KeyValuePair<string, string> kvp in param)   {    builder.Append($"{WebUtility.UrlEncode(kvp.Key)}={WebUtility.UrlEncode(kvp.Value)}&");   }   return builder.ToString().TrimEnd('&');  }  public async Task<HttpResponseMessage> GetRequestAsync(string url, Dictionary<string, string> param)  {   StringBuilder urlBuilder = new StringBuilder($"{baseUrl.TrimEnd('/')}{url}?");   string fullurl = AppendQuery(urlBuilder, param);   string payload = "";   Dictionary<string, string> headers = new Dictionary<string, string>();   return await this.Send(HttpMethod.Get, fullurl, payload, headers);  }  public async Task<HttpResponseMessage> GetRequestAsync(string path, string queryString, Dictionary<string, string> headers)  {   string fullurl = $"{this.baseUrl.TrimEnd('/')}{path}?{queryString}";   string payload = "";   return await this.Send(HttpMethod.Get, fullurl, payload, headers);  }  public async Task<HttpResponseMessage> PostRequestAsync(string path, string payload, Dictionary<string, string> headers)  {   string fullurl = $"{baseUrl.TrimEnd('/')}{path}";   return await this.Send(HttpMethod.Post, fullurl, payload, headers);  }  public async Task<HttpResponseMessage> PostRequestAsync(string url, Dictionary<string, string> param)  {   string fullurl = $"{this.baseUrl.TrimEnd('/')}{url}?";   StringBuilder payloadBuilder = new StringBuilder();   string payload = AppendQuery(payloadBuilder, param);   Dictionary<string, string> headers = new Dictionary<string, string>();   headers["Content-Type"] = "application/x-www-form-urlencoded";   return await this.Send(HttpMethod.Post, fullurl, payload, headers);  }  private async Task<HttpResponseMessage> Send(HttpMethod method, string url, string payload, Dictionary<string, string> headers)  {   using (var cts = new System.Threading.CancellationTokenSource(timeout * 1000))   {    using (var msg = new HttpRequestMessage(method, url))    {     foreach (KeyValuePair<string, string> kvp in headers)     {      if (kvp.Key.Equals("Content-Type"))      {       msg.Content = new StringContent(payload, Encoding.UTF8, kvp.Value);      }      else if (kvp.Key.Equals("Host"))      {       msg.Headers.Host = kvp.Value;      }      else if (kvp.Key.Equals("Authorization"))      {       msg.Headers.Authorization = new AuthenticationHeaderValue("TC3-HMAC-SHA256", kvp.Value.Substring("TC3-HMAC-SHA256".Length));      }      else      {       msg.Headers.Add(kvp.Key, kvp.Value);      }     }     return await http.SendAsync(msg, cts.Token);    }   }  } }}

  

 

/*
  * Copyright (c) 2018 THL A29 Limited, a Tencent company. All Rights Reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * >  *
  * Unless required by applicable law or agreed to in writing,
  * software distributed under the License is distributed on an
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  * KIND, either express or implied. See the License for the
  * specific language governing permissions and limitations
  * under the License.
  */
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Net;
 using System.Net.Http;
 using System.Net.Http.Headers;
 using System.Text;
 using System.Threading.Tasks;
  
 namespace TencentCloud.Common.Http
 {
 public class HttpConnection
 {
 private class HttpClientHolder
 {
 private static readonly ConcurrentDictionary<string, HttpClientHolder> httpclients = new ConcurrentDictionary<string, HttpClientHolder>();
  
 public static HttpClient GetClient(string proxy)
 {
 string key = string.IsNullOrEmpty(proxy) ? "" : proxy;
 HttpClientHolder result = httpclients.GetOrAdd(key, (k) =>
 {
 return new HttpClientHolder(k);
 });
 TimeSpan timeSpan = DateTime.Now - result.createTime;
  
 // 每5分钟创建一个新的连接,放弃旧连接,避免DNS刷新问题。
 while (timeSpan.TotalSeconds > 300)
 {
 ICollection<KeyValuePair<string, HttpClientHolder>> kv = httpclients;
 kv.Remove(new KeyValuePair<string, HttpClientHolder>(key, result));
 result = httpclients.GetOrAdd(key, (k) =>
 {
 return new HttpClientHolder(k);
 });
 timeSpan = DateTime.Now - result.createTime;
 }
 return result.client;
 }
  
 public readonly HttpClient client;
  
 public readonly DateTime createTime;
  
 public HttpClientHolder(string proxy)
 {
 string p = string.IsNullOrEmpty(proxy) ? "" : proxy;
 if (p == "")
 {
 this.client = new HttpClient();
 }
 else
 {
 var httpClientHandler = new HttpClientHandler
 {
 Proxy = new WebProxy(proxy),
 };
  
 this.client = new HttpClient(handler: httpClientHandler, disposeHandler: true);
 }
 this.client.Timeout = TimeSpan.FromSeconds(60);
 this.createTime = DateTime.Now;
 }
 }
  
 private readonly HttpClient http;
  
 private readonly string baseUrl;
  
 private readonly string proxy;
  
 private readonly int timeout;
  
 public HttpConnection(string baseUrl, int timeout, string proxy, HttpClient http)
 {
 this.proxy = string.IsNullOrEmpty(proxy) ? "" : proxy;
 this.timeout = timeout;
 this.baseUrl = baseUrl;
 if (http != null)
 {
 this.http = http;
 }
 else
 {
 this.http = HttpClientHolder.GetClient(this.proxy);
 }
 }
  
 private static string AppendQuery(StringBuilder builder, Dictionary<string, string> param)
 {
 foreach (KeyValuePair<string, string> kvp in param)
 {
 builder.Append($"{WebUtility.UrlEncode(kvp.Key)}={WebUtility.UrlEncode(kvp.Value)}&");
 }
 return builder.ToString().TrimEnd('&');
 }
  
 public async Task<HttpResponseMessage> GetRequestAsync(string url, Dictionary<string, string> param)
 {
 StringBuilder urlBuilder = new StringBuilder($"{baseUrl.TrimEnd('/')}{url}?");
 string fullurl = AppendQuery(urlBuilder, param);
 string payload = "";
 Dictionary<string, string> headers = new Dictionary<string, string>();
 return await this.Send(HttpMethod.Get, fullurl, payload, headers);
 }
  
 public async Task<HttpResponseMessage> GetRequestAsync(string path, string queryString, Dictionary<string, string> headers)
 {
 string fullurl = $"{this.baseUrl.TrimEnd('/')}{path}?{queryString}";
 string payload = "";
 return await this.Send(HttpMethod.Get, fullurl, payload, headers);
 }
  
 public async Task<HttpResponseMessage> PostRequestAsync(string path, string payload, Dictionary<string, string> headers)
 {
 string fullurl = $"{baseUrl.TrimEnd('/')}{path}";
 return await this.Send(HttpMethod.Post, fullurl, payload, headers);
 }
  
 public async Task<HttpResponseMessage> PostRequestAsync(string url, Dictionary<string, string> param)
 {
 string fullurl = $"{this.baseUrl.TrimEnd('/')}{url}?";
 StringBuilder payloadBuilder = new StringBuilder();
 string payload = AppendQuery(payloadBuilder, param);
 Dictionary<string, string> headers = new Dictionary<string, string>();
 headers["Content-Type"] = "application/x-www-form-urlencoded";
 return await this.Send(HttpMethod.Post, fullurl, payload, headers);
 }
  
 private async Task<HttpResponseMessage> Send(HttpMethod method, string url, string payload, Dictionary<string, string> headers)
 {
 using (var cts = new System.Threading.CancellationTokenSource(timeout * 1000))
 {
 using (var msg = new HttpRequestMessage(method, url))
 {
 foreach (KeyValuePair<string, string> kvp in headers)
 {
 if (kvp.Key.Equals("Content-Type"))
 {
 msg.Content = new StringContent(payload, Encoding.UTF8, kvp.Value);
 }
 else if (kvp.Key.Equals("Host"))
 {
 msg.Headers.Host = kvp.Value;
 }
 else if (kvp.Key.Equals("Authorization"))
 {
 msg.Headers.Authorization = new AuthenticationHeaderValue("TC3-HMAC-SHA256", kvp.Value.Substring("TC3-HMAC-SHA256".Length));
 }
 else
 {
 msg.Headers.Add(kvp.Key, kvp.Value);
 }
 }
 return await http.SendAsync(msg, cts.Token);
 }
 }
 }
 }
 }

原文转载:http://www.shaoqun.com/a/485817.html

香港会计师事务所:https://www.ikjzd.com/w/2434

worldfirst:https://www.ikjzd.com/w/289

黄远:https://www.ikjzd.com/w/1785


参照腾讯云sdk链接https://github.com/TencentCloud/tencentcloud-sdk-dotnet/blob/master/TencentCloud/Common/Http/HttpConnection.cs减小创建的开销可以用单例,也可以用请求池,后续再简单写个请求池,这次主要贴下腾讯的代码,照着腾讯sdk的请求方式可以直接搬到自己的项目中去使用代码就不一一解释了
usps国际快递查询:https://www.ikjzd.com/w/513
trax:https://www.ikjzd.com/w/1489
美国站如何注册?2018年亚马逊美国站注册新变化及流程揭秘!:https://www.ikjzd.com/home/1660
30天学会开店:从零开始了解shopify之Facebook广告创意制作--Day20:https://www.ikjzd.com/home/108453
手把手教你如何通过产品介绍来提高亚马逊上的月销量!:https://www.ikjzd.com/home/124507

No comments:

Post a Comment