|
|
@ -48,6 +48,7 @@
|
|
|
|
"source": [
|
|
|
|
"source": [
|
|
|
|
"//全局设置,行运行一次,为后续准备\n",
|
|
|
|
"//全局设置,行运行一次,为后续准备\n",
|
|
|
|
"#r \"nuget:System.Net.Http.Json\"\n",
|
|
|
|
"#r \"nuget:System.Net.Http.Json\"\n",
|
|
|
|
|
|
|
|
"#r \"nuget:Microsoft.Net.Http.Headers\"\n",
|
|
|
|
"#r \"nuget:Microsoft.Extensions.Http\"\n",
|
|
|
|
"#r \"nuget:Microsoft.Extensions.Http\"\n",
|
|
|
|
"#r \"nuget:Microsoft.Extensions.DependencyInjection\"\n",
|
|
|
|
"#r \"nuget:Microsoft.Extensions.DependencyInjection\"\n",
|
|
|
|
"#r \"nuget:Microsoft.Extensions.Logging\" \n",
|
|
|
|
"#r \"nuget:Microsoft.Extensions.Logging\" \n",
|
|
|
@ -1999,6 +2000,12 @@
|
|
|
|
"cell_type": "code",
|
|
|
|
"cell_type": "code",
|
|
|
|
"execution_count": null,
|
|
|
|
"execution_count": null,
|
|
|
|
"metadata": {
|
|
|
|
"metadata": {
|
|
|
|
|
|
|
|
"dotnet_interactive": {
|
|
|
|
|
|
|
|
"language": "csharp"
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
"polyglot_notebook": {
|
|
|
|
|
|
|
|
"kernelName": "csharp"
|
|
|
|
|
|
|
|
},
|
|
|
|
"vscode": {
|
|
|
|
"vscode": {
|
|
|
|
"languageId": "polyglot-notebook"
|
|
|
|
"languageId": "polyglot-notebook"
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -2048,6 +2055,12 @@
|
|
|
|
"cell_type": "code",
|
|
|
|
"cell_type": "code",
|
|
|
|
"execution_count": null,
|
|
|
|
"execution_count": null,
|
|
|
|
"metadata": {
|
|
|
|
"metadata": {
|
|
|
|
|
|
|
|
"dotnet_interactive": {
|
|
|
|
|
|
|
|
"language": "csharp"
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
"polyglot_notebook": {
|
|
|
|
|
|
|
|
"kernelName": "csharp"
|
|
|
|
|
|
|
|
},
|
|
|
|
"vscode": {
|
|
|
|
"vscode": {
|
|
|
|
"languageId": "polyglot-notebook"
|
|
|
|
"languageId": "polyglot-notebook"
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -2097,6 +2110,320 @@
|
|
|
|
"source": [
|
|
|
|
"source": [
|
|
|
|
"## 8、综合管理:工厂 + 类型化客户端 + 请求管道 + Polly(默认使用 连接池和IoC容器)"
|
|
|
|
"## 8、综合管理:工厂 + 类型化客户端 + 请求管道 + Polly(默认使用 连接池和IoC容器)"
|
|
|
|
]
|
|
|
|
]
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
"cell_type": "markdown",
|
|
|
|
|
|
|
|
"metadata": {},
|
|
|
|
|
|
|
|
"source": [
|
|
|
|
|
|
|
|
"### 综合示例1"
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
|
|
|
"execution_count": null,
|
|
|
|
|
|
|
|
"metadata": {
|
|
|
|
|
|
|
|
"dotnet_interactive": {
|
|
|
|
|
|
|
|
"language": "csharp"
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
"polyglot_notebook": {
|
|
|
|
|
|
|
|
"kernelName": "csharp"
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
"vscode": {
|
|
|
|
|
|
|
|
"languageId": "polyglot-notebook"
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
"outputs": [],
|
|
|
|
|
|
|
|
"source": [
|
|
|
|
|
|
|
|
"/* 综合示例1\n",
|
|
|
|
|
|
|
|
" 工厂 + 类型化客户端 + 管道 + Polly + 日志(自定义) \n",
|
|
|
|
|
|
|
|
"*/\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
"//类型化客户端\n",
|
|
|
|
|
|
|
|
"public class HelloApiService \n",
|
|
|
|
|
|
|
|
"{\n",
|
|
|
|
|
|
|
|
" public HttpClient Client { get; set; }\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" public HelloApiService(HttpClient httpClient)\n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" Client = httpClient;\n",
|
|
|
|
|
|
|
|
" }\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" public async Task<string> Ping()\n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" var content = await Client.GetStringAsync(\"/api/Hello/Ping\");\n",
|
|
|
|
|
|
|
|
" return content;\n",
|
|
|
|
|
|
|
|
" }\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" public async Task<string> Index()\n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" var content = await Client.GetStringAsync(\"/api/Hello/Index\");\n",
|
|
|
|
|
|
|
|
" return content;\n",
|
|
|
|
|
|
|
|
" }\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" public async Task<string> Get()\n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" var content = await Client.GetStringAsync(\"/api/Hello/Get\");\n",
|
|
|
|
|
|
|
|
" return content;\n",
|
|
|
|
|
|
|
|
" }\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" public async Task<string> Post()\n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" var response = await Client.PostAsync(\"/api/Hello/Post\", null);\n",
|
|
|
|
|
|
|
|
" var content = await response.Content.ReadAsStringAsync();\n",
|
|
|
|
|
|
|
|
" return content;\n",
|
|
|
|
|
|
|
|
" }\n",
|
|
|
|
|
|
|
|
"}\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
"//类开型客户端\n",
|
|
|
|
|
|
|
|
"public class Polly8ApiService \n",
|
|
|
|
|
|
|
|
"{\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" public HttpClient Client { get; set; }\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" public Polly8ApiService(HttpClient httpClient)\n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" Client = httpClient;\n",
|
|
|
|
|
|
|
|
" } \n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" public async Task<string> Hello()\n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" var content = await Client.GetStringAsync(\"/api/Polly8/Hello\");\n",
|
|
|
|
|
|
|
|
" return content;\n",
|
|
|
|
|
|
|
|
" }\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" public async Task<string> Exception()\n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" var response = await Client.GetAsync(\"/api/Polly8/Exception\");\n",
|
|
|
|
|
|
|
|
" response.EnsureSuccessStatusCode();\n",
|
|
|
|
|
|
|
|
" var content = await response.Content.ReadAsStringAsync();\n",
|
|
|
|
|
|
|
|
" return content;\n",
|
|
|
|
|
|
|
|
" }\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" public async Task<string> RetryException()\n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" var response = await Client.GetAsync(\"/api/Polly8/RetryException\");\n",
|
|
|
|
|
|
|
|
" response.EnsureSuccessStatusCode();\n",
|
|
|
|
|
|
|
|
" var content = await response.Content.ReadAsStringAsync();\n",
|
|
|
|
|
|
|
|
" return content;\n",
|
|
|
|
|
|
|
|
" }\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" public async Task<string> RandomException()\n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" var response = await Client.GetAsync(\"/api/Polly8/RandomException\");\n",
|
|
|
|
|
|
|
|
" response.EnsureSuccessStatusCode();\n",
|
|
|
|
|
|
|
|
" var content = await response.Content.ReadAsStringAsync();\n",
|
|
|
|
|
|
|
|
" return content;\n",
|
|
|
|
|
|
|
|
" }\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" public async Task<string> ToggleException()\n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" var response = await Client.GetAsync(\"/api/Polly8/ToggleException?toggleId=\"+Guid.NewGuid().ToString());\n",
|
|
|
|
|
|
|
|
" response.EnsureSuccessStatusCode();\n",
|
|
|
|
|
|
|
|
" var content = await response.Content.ReadAsStringAsync();\n",
|
|
|
|
|
|
|
|
" return content;\n",
|
|
|
|
|
|
|
|
" }\n",
|
|
|
|
|
|
|
|
"}\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
"//Token管理中间件\n",
|
|
|
|
|
|
|
|
"public class TokenDelegatingHandler : DelegatingHandler \n",
|
|
|
|
|
|
|
|
"{\n",
|
|
|
|
|
|
|
|
" protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken)\n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" Console.WriteLine(\"TokenDelegatingHandler -> Send -> Added Token\");\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" if (!request.Headers.Contains(Microsoft.Net.Http.Headers.HeaderNames.Authorization)) \n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" Console.WriteLine(\"没有 Token, TokenDelegatingHandler 添加之\");\n",
|
|
|
|
|
|
|
|
" request.Headers.Add(Microsoft.Net.Http.Headers.HeaderNames.Authorization, \"Bearer \" + \"a.b.c\");\n",
|
|
|
|
|
|
|
|
" }\n",
|
|
|
|
|
|
|
|
" else\n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" Console.WriteLine($\"已有Token, {request.Headers.Authorization}\");\n",
|
|
|
|
|
|
|
|
" }\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" HttpResponseMessage response = base.Send(request, cancellationToken);\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" Console.WriteLine(\"TokenDelegatingHandler -> Send -> After\");\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" return response;\n",
|
|
|
|
|
|
|
|
" }\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" Console.WriteLine(\"TokenDelegatingHandler -> SendAsync -> Before\");\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" HttpResponseMessage response = await base.SendAsync(request, cancellationToken);\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" Console.WriteLine(\"TokenDelegatingHandler -> SendAsync -> After\");\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" return response;\n",
|
|
|
|
|
|
|
|
" }\n",
|
|
|
|
|
|
|
|
"}\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
"//自定义日志\n",
|
|
|
|
|
|
|
|
"public class CustomLogger : IHttpClientLogger\n",
|
|
|
|
|
|
|
|
"{\n",
|
|
|
|
|
|
|
|
" public object? LogRequestStart(HttpRequestMessage request)\n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" return null;\n",
|
|
|
|
|
|
|
|
" }\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" public void LogRequestStop(object? ctx, HttpRequestMessage request, HttpResponseMessage response, TimeSpan elapsed)\n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" Console.WriteLine($\"自定义日志:{request.Method} {request.RequestUri?.AbsoluteUri} - {(int)response.StatusCode} {response.StatusCode} in {elapsed.TotalMilliseconds}ms\");\n",
|
|
|
|
|
|
|
|
" }\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" public void LogRequestFailed(object? ctx, HttpRequestMessage request, HttpResponseMessage? response, Exception e, TimeSpan elapsed)\n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" Console.WriteLine($\"自定义日志:{request.Method} {request.RequestUri?.AbsoluteUri} - Exception {e.GetType().FullName}: {e.Message}\");\n",
|
|
|
|
|
|
|
|
" }\n",
|
|
|
|
|
|
|
|
"}\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
"//polly策略\n",
|
|
|
|
|
|
|
|
"var policy = Policy\n",
|
|
|
|
|
|
|
|
" .Handle<HttpRequestException>()\n",
|
|
|
|
|
|
|
|
" .OrResult<HttpResponseMessage>(message => message.StatusCode != System.Net.HttpStatusCode.OK)\n",
|
|
|
|
|
|
|
|
" .WaitAndRetryAsync(new TimeSpan[]{TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2),TimeSpan.FromSeconds(4),});\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
"//使用\n",
|
|
|
|
|
|
|
|
"{\n",
|
|
|
|
|
|
|
|
" var services = new ServiceCollection();\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" //注册基础类型\n",
|
|
|
|
|
|
|
|
" services\n",
|
|
|
|
|
|
|
|
" //注册日志类\n",
|
|
|
|
|
|
|
|
" .AddTransient<CustomLogger>()\n",
|
|
|
|
|
|
|
|
" .AddScoped<TokenDelegatingHandler>()\n",
|
|
|
|
|
|
|
|
" ;\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" //基础配置\n",
|
|
|
|
|
|
|
|
" services\n",
|
|
|
|
|
|
|
|
" // 基础日志配置(默认日志)\n",
|
|
|
|
|
|
|
|
" .AddLogging(builder => \n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" //日志级别\n",
|
|
|
|
|
|
|
|
" builder.SetMinimumLevel(LogLevel.Trace);\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" //控制台日志\n",
|
|
|
|
|
|
|
|
" builder.AddConsole();\n",
|
|
|
|
|
|
|
|
" })\n",
|
|
|
|
|
|
|
|
" //全局配置\n",
|
|
|
|
|
|
|
|
" .ConfigureHttpClientDefaults(clientBuilder =>\n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" clientBuilder.AddDefaultLogger();\n",
|
|
|
|
|
|
|
|
" clientBuilder.ConfigureHttpClient(client => \n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" client.BaseAddress = new Uri(webApiBaseUrl);\n",
|
|
|
|
|
|
|
|
" });\n",
|
|
|
|
|
|
|
|
" });\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" //默认命名客户端\n",
|
|
|
|
|
|
|
|
" services.AddHttpClient<HttpClient>(string.Empty, config => \n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" config.DefaultRequestHeaders.Add(\"X-Custom-Demo\", \"true\");\n",
|
|
|
|
|
|
|
|
" })\n",
|
|
|
|
|
|
|
|
" //配置客户端\n",
|
|
|
|
|
|
|
|
" .ConfigureHttpClient(client => \n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" //client.BaseAddress = new Uri(webApiBaseUrl);\n",
|
|
|
|
|
|
|
|
" client.Timeout = TimeSpan.FromSeconds(10);\n",
|
|
|
|
|
|
|
|
" })\n",
|
|
|
|
|
|
|
|
" //添加类型化客户端\n",
|
|
|
|
|
|
|
|
" .AddTypedClient<HelloApiService>()\n",
|
|
|
|
|
|
|
|
" //添加自定义管道\n",
|
|
|
|
|
|
|
|
" .AddHttpMessageHandler<TokenDelegatingHandler>()\n",
|
|
|
|
|
|
|
|
" //添加默认日志:全局配置已添加\n",
|
|
|
|
|
|
|
|
" //.AddDefaultLogger()\n",
|
|
|
|
|
|
|
|
" //添加自定义日志\n",
|
|
|
|
|
|
|
|
" .AddLogger<CustomLogger>()\n",
|
|
|
|
|
|
|
|
" //日志转发头(所有请求头)\n",
|
|
|
|
|
|
|
|
" .RedactLoggedHeaders( headerName => true)\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" //配置SocketsHttpHandler\n",
|
|
|
|
|
|
|
|
" .UseSocketsHttpHandler(config =>\n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" //配置连接池等\n",
|
|
|
|
|
|
|
|
" config.Configure((handler,provider) => \n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" handler.AllowAutoRedirect = true;\n",
|
|
|
|
|
|
|
|
" handler.PooledConnectionIdleTimeout = TimeSpan.FromSeconds(30);\n",
|
|
|
|
|
|
|
|
" handler.PooledConnectionLifetime = TimeSpan.FromSeconds(30);\n",
|
|
|
|
|
|
|
|
" handler.UseProxy = false;\n",
|
|
|
|
|
|
|
|
" handler.UseCookies = true;\n",
|
|
|
|
|
|
|
|
" });\n",
|
|
|
|
|
|
|
|
" })\n",
|
|
|
|
|
|
|
|
" //设置生命周期\n",
|
|
|
|
|
|
|
|
" .SetHandlerLifetime(TimeSpan.FromSeconds(30))\n",
|
|
|
|
|
|
|
|
" //Polly策略配置\n",
|
|
|
|
|
|
|
|
" .AddPolicyHandler(policy)\n",
|
|
|
|
|
|
|
|
" //便捷配置\n",
|
|
|
|
|
|
|
|
" .AddTransientHttpErrorPolicy(builder => builder.CircuitBreakerAsync<HttpResponseMessage>(11, TimeSpan.FromSeconds(30)))\n",
|
|
|
|
|
|
|
|
" ;\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" //自定义\n",
|
|
|
|
|
|
|
|
" services.AddHttpClient<HttpClient>(\"ClientA\", config => \n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" config.DefaultRequestHeaders.Add(\"X-Custom-Demo\", \"ClientA\");\n",
|
|
|
|
|
|
|
|
" })\n",
|
|
|
|
|
|
|
|
" //配置客户端\n",
|
|
|
|
|
|
|
|
" .ConfigureHttpClient(client => \n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" //client.BaseAddress = new Uri(webApiBaseUrl);\n",
|
|
|
|
|
|
|
|
" client.Timeout = TimeSpan.FromSeconds(10);\n",
|
|
|
|
|
|
|
|
" })\n",
|
|
|
|
|
|
|
|
" //添加类型化客户端\n",
|
|
|
|
|
|
|
|
" .AddTypedClient<Polly8ApiService>()\n",
|
|
|
|
|
|
|
|
" //添加自定义管道\n",
|
|
|
|
|
|
|
|
" .AddHttpMessageHandler<TokenDelegatingHandler>()\n",
|
|
|
|
|
|
|
|
" //添加默认日志:全局配置已添加\n",
|
|
|
|
|
|
|
|
" //.AddDefaultLogger()\n",
|
|
|
|
|
|
|
|
" //添加自定义日志\n",
|
|
|
|
|
|
|
|
" .AddLogger<CustomLogger>()\n",
|
|
|
|
|
|
|
|
" //日志转发头(所有请求头)\n",
|
|
|
|
|
|
|
|
" .RedactLoggedHeaders( headerName => true)\n",
|
|
|
|
|
|
|
|
" //配置SocketsHttpHandler\n",
|
|
|
|
|
|
|
|
" .UseSocketsHttpHandler(config =>\n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" //配置连接池等\n",
|
|
|
|
|
|
|
|
" config.Configure((handler,provider) => \n",
|
|
|
|
|
|
|
|
" {\n",
|
|
|
|
|
|
|
|
" handler.AllowAutoRedirect = true;\n",
|
|
|
|
|
|
|
|
" handler.PooledConnectionIdleTimeout = TimeSpan.FromSeconds(30);\n",
|
|
|
|
|
|
|
|
" handler.PooledConnectionLifetime = TimeSpan.FromSeconds(30);\n",
|
|
|
|
|
|
|
|
" handler.UseProxy = false;\n",
|
|
|
|
|
|
|
|
" handler.UseCookies = true;\n",
|
|
|
|
|
|
|
|
" });\n",
|
|
|
|
|
|
|
|
" })\n",
|
|
|
|
|
|
|
|
" //设置生命周期\n",
|
|
|
|
|
|
|
|
" .SetHandlerLifetime(TimeSpan.FromSeconds(30))\n",
|
|
|
|
|
|
|
|
" //Polly策略配置\n",
|
|
|
|
|
|
|
|
" .AddPolicyHandler(policy)\n",
|
|
|
|
|
|
|
|
" //便捷配置\n",
|
|
|
|
|
|
|
|
" .AddTransientHttpErrorPolicy(builder => builder.CircuitBreakerAsync<HttpResponseMessage>(11, TimeSpan.FromSeconds(30)))\n",
|
|
|
|
|
|
|
|
" ;\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" var factory = services.BuildServiceProvider().GetRequiredService<IHttpClientFactory>();\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" var defaultClient = factory.CreateClient();\n",
|
|
|
|
|
|
|
|
" var defaultContent = await defaultClient.GetStringAsync(\"api/hello/ping\");\n",
|
|
|
|
|
|
|
|
" Console.WriteLine(defaultContent);\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" var clientA = factory.CreateClient();\n",
|
|
|
|
|
|
|
|
" var contentA = await clientA.GetStringAsync(\"api/polly8/hello\");\n",
|
|
|
|
|
|
|
|
" Console.WriteLine(contentA);\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" //类型化客户端\n",
|
|
|
|
|
|
|
|
" HelloApiService helloApiService = services.BuildServiceProvider().GetRequiredService<HelloApiService>();\n",
|
|
|
|
|
|
|
|
" Console.WriteLine(await helloApiService.Ping());\n",
|
|
|
|
|
|
|
|
" Console.WriteLine(await helloApiService.Index());\n",
|
|
|
|
|
|
|
|
" Console.WriteLine(await helloApiService.Get());\n",
|
|
|
|
|
|
|
|
" Console.WriteLine(await helloApiService.Post());\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
" Polly8ApiService polly8ApiService = services.BuildServiceProvider().GetRequiredService<Polly8ApiService>();\n",
|
|
|
|
|
|
|
|
" Console.WriteLine(await polly8ApiService.Hello());\n",
|
|
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
|
|
"}\n"
|
|
|
|
|
|
|
|
]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
],
|
|
|
|
],
|
|
|
|
"metadata": {
|
|
|
|
"metadata": {
|
|
|
|