推送邏輯是在類庫中使用HttpClient,所以沒有使用HttpClientFactory,因此定義靜態(tài)變量來使用HttpClient,而非每一個請求就實例化一個HttpClient,
接下來我們來詳細(xì)分析項目示例代碼并對其進行改進
static class Program
{
static HttpClient httpClient = CreateHttpClient();
static Program()
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
ServicePointManager.ServerCertificateValidationCallback = (message, cert, chain, error) => true,
}
static async Task Main(string[] args)
{
await httpClient.PostAsync("", new StringContent(""));
}
static HttpClient CreateHttpClient()
{
var client = new HttpClient(new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true
})
{
Timeout = TimeSpan.FromSeconds(30)
};
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("ContentType", "application/json");
return client;
}
}
若對接方僅使用HTTPS協(xié)議,無需驗證證書,最好是忽略證書驗證,否則有可能會引起建立驗證證書連接異常,即添加
ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true
我們觀察上述代碼,有兩個地方都對證書驗證進行了設(shè)置,一個是在靜態(tài)構(gòu)造函數(shù)中ServicePointManager(簡稱SP),另外則在實例化HttpClient構(gòu)造函數(shù)中即HttpClientHandler(簡稱HCH),那么這二者是否有使用上的限制呢?
在.NET Framework中,內(nèi)置的HttpClient建立在HttpWebRequest之上,因此可以使用SP來配置
在.NET Core中,通過SP配置證書信息僅影響HttpWebRequest,而對HttpClient無效,需通過HCH配置來達(dá)到相同目的
所以去除在靜態(tài)構(gòu)造函數(shù)中對忽略證書的配置,改為在HttpClientHandler中
var client = new HttpClient(new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true,
SslProtocols = SslProtocols.Tls12
})
?
配置keep-alive我們俗稱為?;顧C制,所以在默認(rèn)請求頭中添加如下一行
//增加?;顧C制,表明連接為長連接 client.DefaultRequestHeaders.Connection.Add("keep-alive");
上述只是在報文頭中添加持久化連接標(biāo)識,但不意味著就一定生效,因為默認(rèn)是禁用持久化連接,所以為了保險起見,添加如下代碼
//啟用保活機制(保持活動超時設(shè)置為 2 小時,并將保持活動間隔設(shè)置為 1 秒。) ServicePointManager.SetTcpKeepAlive(true, 7200000, 1000);
public static void SetTcpKeepAlive(bool enabled, int keepAliveTime, int keepAliveInterval)
{
if (enabled)
{
if (keepAliveTime <= 0)
{
throw new ArgumentOutOfRangeException(nameof(keepAliveTime));
}
if (keepAliveInterval <= 0)
{
throw new ArgumentOutOfRangeException(nameof(keepAliveInterval));
}
}
}
最關(guān)鍵的一點則是默認(rèn)持久化連接數(shù)為2,非持久化連接為4
public class ServicePointManager { public const int DefaultNonPersistentConnectionLimit = 4; public const int DefaultPersistentConnectionLimit = 2; private ServicePointManager() { } }文章來源:http://www.zghlxwxcb.cn/news/detail-771090.html
那么問題是否就已很明了,項目中使用非持久化連接,即連接為4,未深究源碼具體細(xì)節(jié),大膽猜想一下,若連接大于4,是否會出現(xiàn)將此前連接主動關(guān)閉,重建新的連接請求呢?最終我們將原始代碼修改為如下形式文章來源地址http://www.zghlxwxcb.cn/news/detail-771090.html
static class Program
{
static HttpClient httpClient = CreateHttpClient();
static Program()
{
//默認(rèn)連接數(shù)限制為2,增加連接數(shù)限制
ServicePointManager.DefaultConnectionLimit = 512;
//啟用?;顧C制(保持活動超時設(shè)置為 2 小時,并將保持活動間隔設(shè)置為 1 秒。)
ServicePointManager.SetTcpKeepAlive(true, 7200000, 1000);
}
static async Task Main(string[] args)
{
await httpClient.PostAsync("", new StringContent(""));
Console.WriteLine("Hello World!");
}
static HttpClient CreateHttpClient()
{
var client = new HttpClient(new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true,
SslProtocols = SslProtocols.Tls12
})
{
Timeout = TimeSpan.FromSeconds(30)
};
client.DefaultRequestHeaders.Accept.Clear();
//增加保活機制,表明連接為長連接
client.DefaultRequestHeaders.Connection.Add("keep-alive");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("ContentType", "application/json");
return client;
}
}
到了這里,關(guān)于.NET Core HttpClient請求異常分析的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!