main
bicijinlian 1 month ago
parent 0c990e96ac
commit 9a978d7453

@ -75,10 +75,8 @@
"\n", "\n",
"global using Microsoft.Extensions.DependencyInjection;\n", "global using Microsoft.Extensions.DependencyInjection;\n",
"global using Microsoft.Extensions.DependencyInjection.Extensions;\n", "global using Microsoft.Extensions.DependencyInjection.Extensions;\n",
"\n",
"global using Microsoft.Extensions.Logging;\n", "global using Microsoft.Extensions.Logging;\n",
"global using Microsoft.Extensions.Logging.Console;\n", "global using Microsoft.Extensions.Logging.Console;\n",
"\n",
"global using Microsoft.Extensions.Http.Logging;\n", "global using Microsoft.Extensions.Http.Logging;\n",
"\n", "\n",
"\n", "\n",
@ -1748,6 +1746,18 @@
"## 7 工厂 + Polly V8" "## 7 工厂 + Polly V8"
] ]
}, },
{
"cell_type": "markdown",
"metadata": {},
"source": [
"IFactoryHttpClient 与 Polly配合可轻松实现重试、熔断、降级、限流等功能本文只是简略的给出常用的使用方法详情会写在 Polly学习项目中。[Polly 官方参考](https://github.com/App-vNext/Polly/wiki/Polly-and-HttpClientFactory)\n",
"使用步骤:\n",
"1. 引用 Polly v8 和 Microsoft.Extensions.Http.Polly 包\n",
"2. 配置命名客户端\n",
"3. 使用 AddTransientHttpErrorPolicy 快捷方法,配置策略\n",
"4. 使用其它方式配置,并且可以使用多策略、注册策略、上下文等功能"
]
},
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
@ -1759,10 +1769,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"工厂可以和Polly(v8)一起使用:\n", "使用快捷方法AddTransientHttpErrorPolicy进行常用功能使用。"
"1. 引用 Polly v8 和 Microsoft.Extensions.Http.Polly 包\n",
"2. 配置命名客户端\n",
"3. 使用 AddTransientHttpErrorPolicy 配置策略"
] ]
}, },
{ {
@ -1781,31 +1788,33 @@
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"//便捷应用AddTransientHttpErrorPolicy() 方法,添加常用瞬时错误重试策略\n", "/*\n",
" 便捷应用AddTransientHttpErrorPolicy() 方法,添加常用瞬时错误重试策略\n",
"*/\n",
"{\n", "{\n",
" var services = new ServiceCollection();\n", " var services = new ServiceCollection();\n",
"\n", "\n",
" services.AddHttpClient(\"ClientA\")\n", " services.AddHttpClient(string.Empty)\n",
" //配置默认命名客户端\n",
" .ConfigureHttpClient(client => \n", " .ConfigureHttpClient(client => \n",
" {\n", " {\n",
" client.BaseAddress = new Uri(webApiBaseUrl);\n", " client.BaseAddress = new Uri(webApiBaseUrl);\n",
" })\n", " })\n",
" //设置Policy错误处理快捷扩展方法\n",
" .AddTransientHttpErrorPolicy(builder => builder.WaitAndRetryAsync\n", " .AddTransientHttpErrorPolicy(builder => builder.WaitAndRetryAsync\n",
" (\n", " (\n",
" new[]\n", " new[]\n",
" {\n", " {\n",
" TimeSpan.FromSeconds(1),\n", " TimeSpan.FromSeconds(1),\n",
" TimeSpan.FromSeconds(2),\n", " TimeSpan.FromSeconds(2),\n",
" TimeSpan.FromSeconds(4)\n", " TimeSpan.FromSeconds(4),\n",
" }\n", " }\n",
" ))\n", " ))\n",
" .AddTransientHttpErrorPolicy(builder => builder.Fallback<string>());\n", " //可以多次调用:设置多个策略\n",
" .AddTransientHttpErrorPolicy(builder => builder.RetryAsync(1));\n",
" \n", " \n",
" var factory = services.BuildServiceProvider().GetService<IHttpClientFactory>();\n", " var factory = services.BuildServiceProvider().GetService<IHttpClientFactory>();\n",
" var clientA = factory.CreateClient(\"ClientA\");\n", " var content = await factory.CreateClient().GetStringAsync(\"/api/polly8/RandomException\");\n",
" var response = await clientA.GetAsync(\"/api/polly8/RandomException\");\n",
" response.EnsureSuccessStatusCode();\n",
" var content = await response.Content.ReadAsStringAsync();\n",
"\n", "\n",
" Console.WriteLine($\"响应内容:{content}\");\n", " Console.WriteLine($\"响应内容:{content}\");\n",
"}" "}"
@ -1818,6 +1827,13 @@
"### 使用通过传统 Polly 语法配置的任何策略" "### 使用通过传统 Polly 语法配置的任何策略"
] ]
}, },
{
"cell_type": "markdown",
"metadata": {},
"source": [
"使用 AddPolicyHandler 方法及其重载也可用于接受任何 IAsyncPolicy<HttpResponseMessage> ,因此可以定义和应用任何类型的策略:可以指定要处理的内容和处理方式。"
]
},
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
@ -1834,21 +1850,53 @@
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"/*\n",
" 传统方式配置Polly策略\n",
"*/\n",
"//创建策略\n",
"{\n", "{\n",
" var services = new ServiceCollection();\n",
"\n", "\n",
" var policy = Policy.Handle<Exception>()\n", " //重试策略\n",
" .WaitAndRetryAsync\n", " var retryePolicy = Policy\n",
" (\n", " .Handle<HttpRequestException>()\n",
" new[]\n", " .OrResult<HttpResponseMessage>(response => \n",
" {\n", " {\n",
" TimeSpan.FromSeconds(1),\n", " return response.StatusCode == System.Net.HttpStatusCode.Created;\n",
" TimeSpan.FromSeconds(2),\n", " })\n",
" TimeSpan.FromSeconds(4)\n", " .WaitAndRetryAsync(new TimeSpan[]{TimeSpan.FromSeconds(1), TimeSpan.FromMilliseconds(2)});\n",
" }\n", " //调用\n",
" );\n", " services\n",
" .AddHttpClient(string.Empty)\n",
" .AddPolicyHandler(retryePolicy);\n",
"\n",
" //超时策略\n",
" var timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(10);\n",
" services\n",
" .AddHttpClient(\"timeoutPolicy\")\n",
" .AddPolicyHandler(timeoutPolicy);\n",
" \n",
" /* 普通策略转换\n",
" 所有通过 HttpClient 的调用都返回 HttpResponseMessage 因此配置的策略必须是 IAsyncPolicy<HttpResponseMessage> \n",
" 通过简单、便捷的 AsAsyncPolicy<HttpResponseMessage>()方法,将非通用策略 IAsyncPolicy 转换为 IAsyncPolicy<HttpResponseMessage> \n",
" */\n",
" var timeoutPolicy2 = Policy.TimeoutAsync(2);\n",
"\n",
" services\n",
" .AddHttpClient(\"timeoutPolicy2\")\n",
" //转换通用策略\n",
" .AddPolicyHandler(timeoutPolicy2.AsAsyncPolicy<HttpResponseMessage>());\n",
"}\n",
"\n",
"//示例\n",
"{\n",
" //创建策略\n",
" var policy = Policy.RateLimitAsync<HttpResponseMessage>(3,TimeSpan.FromSeconds(10));\n",
"\n",
" //使用\n",
" var services = new ServiceCollection();\n", " var services = new ServiceCollection();\n",
"\n", "\n",
" services.AddHttpClient(\"ClientA\")\n", " services.AddHttpClient(string.Empty)\n",
" .ConfigureHttpClient(client => \n", " .ConfigureHttpClient(client => \n",
" {\n", " {\n",
" client.BaseAddress = new Uri(webApiBaseUrl);\n", " client.BaseAddress = new Uri(webApiBaseUrl);\n",
@ -1866,14 +1914,16 @@
" )\n", " )\n",
" )\n", " )\n",
" .AddPolicyHandler(policy);\n", " .AddPolicyHandler(policy);\n",
" \n", " try\n",
" var factory = services.BuildServiceProvider().GetService<IHttpClientFactory>();\n", " {\n",
" var clientA = factory.CreateClient(\"ClientA\");\n", " var factory = services.BuildServiceProvider().GetService<IHttpClientFactory>();\n",
" var response = await clientA.GetAsync(\"/api/polly8/RandomException\");\n", " var content = await factory.CreateClient().GetStringAsync(\"/api/polly8/RandomException\");\n",
" response.EnsureSuccessStatusCode();\n", " Console.WriteLine($\"响应内容:{content}\");\n",
" var content = await response.Content.ReadAsStringAsync();\n", " }\n",
"\n", " catch(Exception ex)\n",
" Console.WriteLine($\"响应内容:{content}\");\n", " {\n",
" Console.WriteLine($\"未处理的异常:{ex.Message}\");\n",
" }\n",
"}" "}"
] ]
}, },
@ -1891,6 +1941,13 @@
"### 动态选择策略" "### 动态选择策略"
] ]
}, },
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 从注册表中选择策略"
]
},
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},

@ -25,6 +25,16 @@ namespace HttpClientStudy.WebApp.Controllers
_logger = logger; _logger = logger;
} }
/// <summary>
/// 异常接口
/// </summary>
/// <returns></returns>
[HttpGet]
public ActionResult Exception()
{
throw new HttpRequestException("服务器异常");
}
/// <summary> /// <summary>
/// 重试策略异常 /// 重试策略异常
/// </summary> /// </summary>

Loading…
Cancel
Save