Final adjustments to make envoy work with ingress and remove Polly from http calls
This commit is contained in:
parent
c124e9e1ef
commit
08e9b2641a
@ -4,9 +4,12 @@
|
||||
[parameter(Mandatory=$true)][string]$serviceName,
|
||||
[parameter(Mandatory=$true)][string]$dnsNamePrefix,
|
||||
[parameter(Mandatory=$false)][string]$registryName,
|
||||
[parameter(Mandatory=$true)][string]$createAcr=$true,
|
||||
[parameter(Mandatory=$true)][bool]$createAcr=$true,
|
||||
[parameter(Mandatory=$false)][int]$nodeCount=3,
|
||||
[parameter(Mandatory=$false)][string]$nodeVMSize="Standard_D2_v2"
|
||||
[parameter(Mandatory=$false)][string]$nodeVMSize="Standard_D2_v2",
|
||||
[parameter(Mandatory=$false)][bool]$enableHttpApplicationAddon=$true,
|
||||
[parameter(Mandatory=$false)][bool]$enableAzureMonitoring=$false,
|
||||
[parameter(Mandatory=$false)][ValidateSet("VirtualMachineScaleSets","AvailabilitySet",IgnoreCase=$true)]$vmSetType="VirtualMachineScaleSets"
|
||||
)
|
||||
|
||||
# Create resource group
|
||||
@ -15,13 +18,26 @@ az group create --name=$resourceGroupName --location=$location
|
||||
|
||||
if ($createAcr -eq $true) {
|
||||
# Create Azure Container Registry
|
||||
Write-Host "Creating Azure Container Registry..." -ForegroundColor Yellow
|
||||
if ([string]::IsNullOrEmpty($registryName)) {
|
||||
$registryName=$serviceName
|
||||
}
|
||||
Write-Host "Creating Azure Container Registry named $registryName" -ForegroundColor Yellow
|
||||
az acr create -n $registryName -g $resourceGroupName -l $location --admin-enabled true --sku Basic
|
||||
}
|
||||
|
||||
# Create kubernetes cluster in AKS
|
||||
Write-Host "Creating Kubernetes cluster in AKS..." -ForegroundColor Yellow
|
||||
az aks create --resource-group=$resourceGroupName --name=$serviceName --dns-name-prefix=$dnsNamePrefix --generate-ssh-keys --node-count=$nodeCount --node-vm-size=$nodeVMSize
|
||||
Write-Host "Creating AKS $resourceGroupName/$serviceName" -ForegroundColor Yellow
|
||||
az aks create --resource-group=$resourceGroupName --name=$serviceName --dns-name-prefix=$dnsNamePrefix --generate-ssh-keys --node-count=$nodeCount --node-vm-size=$nodeVMSize --vm-set-type $vmSetType
|
||||
|
||||
if ($enableHttpApplicationAddon) {
|
||||
Write-Host "Enabling Http Applciation Routing in AKS $serviceName" -ForegroundColor Yellow
|
||||
az aks enable-addons --resource-group $resourceGroupName --name $serviceName --addons http_application_routing
|
||||
}
|
||||
|
||||
if ($enableAzureMonitoring) {
|
||||
Write-Host "Enabling Azure Monitoring in AKS $serviceName" -ForegroundColor Yellow
|
||||
az aks enable-addons --resource-group $resourceGroupName --name $serviceName --addons monitoring
|
||||
}
|
||||
|
||||
# Retrieve kubernetes cluster configuration and save it under ~/.kube/config
|
||||
Write-Host "Getting Kubernetes config..." -ForegroundColor Yellow
|
||||
@ -29,6 +45,6 @@ az aks get-credentials --resource-group=$resourceGroupName --name=$serviceName
|
||||
|
||||
if ($createAcr -eq $true) {
|
||||
# Show ACR credentials
|
||||
Write-Host "ACR credentials" -ForegroundColor Yellow
|
||||
Write-Host "ACR $registryName credentials:" -ForegroundColor Yellow
|
||||
az acr credential show -n $registryName
|
||||
}
|
||||
|
@ -1,33 +0,0 @@
|
||||
Param(
|
||||
[parameter(Mandatory=$true)][string]$resourceGroupName,
|
||||
[parameter(Mandatory=$true)][string]$location,
|
||||
[parameter(Mandatory=$false)][string]$registryName,
|
||||
[parameter(Mandatory=$true)][string]$orchestratorName,
|
||||
[parameter(Mandatory=$true)][string]$dnsName,
|
||||
[parameter(Mandatory=$true)][string]$createAcr=$true,
|
||||
[parameter(Mandatory=$false)][int]$agentCount=2,
|
||||
[parameter(Mandatory=$false)][string]$agentVMSize="Standard_D2_v2",
|
||||
[parameter(Mandatory=$false)][int]$masterCount=1
|
||||
)
|
||||
|
||||
# Create resource group
|
||||
Write-Host "Creating resource group..." -ForegroundColor Yellow
|
||||
az group create --name=$resourceGroupName --location=$location
|
||||
|
||||
if ($createAcr -eq $true) {
|
||||
# Create Azure Container Registry
|
||||
Write-Host "Creating Azure Container Registry..." -ForegroundColor Yellow
|
||||
az acr create -n $registryName -g $resourceGroupName -l $location --admin-enabled true --sku Basic
|
||||
}
|
||||
|
||||
# Create kubernetes orchestrator
|
||||
Write-Host "Creating kubernetes orchestrator..." -ForegroundColor Yellow
|
||||
az acs create --orchestrator-type=kubernetes --resource-group $resourceGroupName --name=$orchestratorName --dns-prefix=$dnsName --generate-ssh-keys --agent-count=$agentCount --agent-vm-size=$agentVMSize --master-count=$masterCount
|
||||
|
||||
# Retrieve kubernetes cluster configuration and save it under ~/.kube/config
|
||||
az acs kubernetes get-credentials --resource-group=$resourceGroupName --name=$orchestratorName
|
||||
|
||||
if ($createAcr -eq $true) {
|
||||
# Show ACR credentials
|
||||
az acr credential show -n $registryName
|
||||
}
|
@ -23,17 +23,39 @@ static_resources:
|
||||
domains:
|
||||
- "*"
|
||||
routes:
|
||||
- match:
|
||||
- name: "m-short"
|
||||
match:
|
||||
prefix: "/m/"
|
||||
route:
|
||||
auto_host_rewrite: true
|
||||
prefix_rewrite: "/marketing-api/"
|
||||
cluster: marketing
|
||||
- match:
|
||||
- name: "m-long"
|
||||
match:
|
||||
prefix: "/marketing-api/"
|
||||
route:
|
||||
auto_host_rewrite: true
|
||||
cluster: marketing
|
||||
http_filters:
|
||||
- name: envoy.router
|
||||
access_log:
|
||||
- name: envoy.file_access_log
|
||||
filter:
|
||||
not_health_check_filter: {}
|
||||
config:
|
||||
json_format:
|
||||
time: "%START_TIME%"
|
||||
protocol: "%PROTOCOL%"
|
||||
duration: "%DURATION%"
|
||||
request_method: "%REQ(:METHOD)%"
|
||||
request_host: "%REQ(HOST)%"
|
||||
path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
|
||||
response_flags: "%RESPONSE_FLAGS%"
|
||||
route_name: "%ROUTE_NAME%"
|
||||
upstream_host: "%UPSTREAM_HOST%"
|
||||
upstream_cluster: "%UPSTREAM_CLUSTER%"
|
||||
upstream_local_address: "%UPSTREAM_LOCAL_ADDRESS%"
|
||||
path: "/tmp/access.log"
|
||||
clusters:
|
||||
- name: marketing
|
||||
connect_timeout: 0.25s
|
||||
|
@ -23,44 +23,76 @@ static_resources:
|
||||
domains:
|
||||
- "*"
|
||||
routes:
|
||||
- match:
|
||||
- name: "c-short"
|
||||
match:
|
||||
prefix: "/c/"
|
||||
route:
|
||||
auto_host_rewrite: true
|
||||
prefix_rewrite: "/catalog-api/"
|
||||
cluster: catalog
|
||||
- match:
|
||||
- name: "c-long"
|
||||
match:
|
||||
prefix: "/catalog-api/"
|
||||
route:
|
||||
auto_host_rewrite: true
|
||||
cluster: catalog
|
||||
- match:
|
||||
- name: "o-short"
|
||||
match:
|
||||
prefix: "/o/"
|
||||
route:
|
||||
auto_host_rewrite: true
|
||||
prefix_rewrite: "/ordering-api/"
|
||||
cluster: ordering
|
||||
- match:
|
||||
- name: "o-long"
|
||||
match:
|
||||
prefix: "/ordering-api/"
|
||||
route:
|
||||
auto_host_rewrite: true
|
||||
cluster: ordering
|
||||
- match:
|
||||
- name: "b-short"
|
||||
match:
|
||||
prefix: "/b/"
|
||||
route:
|
||||
auto_host_rewrite: true
|
||||
prefix_rewrite: "/basket-api/"
|
||||
cluster: basket
|
||||
- match:
|
||||
- name: "b-long"
|
||||
match:
|
||||
prefix: "/basket-api/"
|
||||
route:
|
||||
auto_host_rewrite: true
|
||||
cluster: basket
|
||||
- match:
|
||||
- name: "agg"
|
||||
match:
|
||||
prefix: "/"
|
||||
route:
|
||||
auto_host_rewrite: true
|
||||
prefix_rewrite: "/"
|
||||
cluster: shoppingagg
|
||||
http_filters:
|
||||
- name: envoy.router
|
||||
access_log:
|
||||
- name: envoy.file_access_log
|
||||
filter:
|
||||
not_health_check_filter: {}
|
||||
config:
|
||||
json_format:
|
||||
time: "%START_TIME%"
|
||||
protocol: "%PROTOCOL%"
|
||||
duration: "%DURATION%"
|
||||
request_method: "%REQ(:METHOD)%"
|
||||
request_host: "%REQ(HOST)%"
|
||||
path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
|
||||
response_flags: "%RESPONSE_FLAGS%"
|
||||
route_name: "%ROUTE_NAME%"
|
||||
upstream_host: "%UPSTREAM_HOST%"
|
||||
upstream_cluster: "%UPSTREAM_CLUSTER%"
|
||||
upstream_local_address: "%UPSTREAM_LOCAL_ADDRESS%"
|
||||
path: "/tmp/access.log"
|
||||
clusters:
|
||||
- name: shoppingagg
|
||||
connect_timeout: 0.25s
|
||||
type: logical_dns
|
||||
type: strict_dns
|
||||
lb_policy: round_robin
|
||||
hosts:
|
||||
- socket_address:
|
||||
@ -68,7 +100,7 @@ static_resources:
|
||||
port_value: 80
|
||||
- name: catalog
|
||||
connect_timeout: 0.25s
|
||||
type: logical_dns
|
||||
type: strict_dns
|
||||
lb_policy: round_robin
|
||||
hosts:
|
||||
- socket_address:
|
||||
@ -76,7 +108,7 @@ static_resources:
|
||||
port_value: 80
|
||||
- name: basket
|
||||
connect_timeout: 0.25s
|
||||
type: logical_dns
|
||||
type: strict_dns
|
||||
lb_policy: round_robin
|
||||
hosts:
|
||||
- socket_address:
|
||||
@ -84,7 +116,7 @@ static_resources:
|
||||
port_value: 80
|
||||
- name: ordering
|
||||
connect_timeout: 0.25s
|
||||
type: logical_dns
|
||||
type: strict_dns
|
||||
lb_policy: round_robin
|
||||
hosts:
|
||||
- socket_address:
|
||||
|
@ -23,21 +23,43 @@ static_resources:
|
||||
domains:
|
||||
- "*"
|
||||
routes:
|
||||
- match:
|
||||
- name: "m-short"
|
||||
match:
|
||||
prefix: "/m/"
|
||||
route:
|
||||
auto_host_rewrite: true
|
||||
prefix_rewrite: "/marketing-api/"
|
||||
cluster: marketing
|
||||
- match:
|
||||
- name: "m-long"
|
||||
match:
|
||||
prefix: "/marketing-api/"
|
||||
route:
|
||||
auto_host_rewrite: true
|
||||
cluster: marketing
|
||||
http_filters:
|
||||
- name: envoy.router
|
||||
access_log:
|
||||
- name: envoy.file_access_log
|
||||
filter:
|
||||
not_health_check_filter: {}
|
||||
config:
|
||||
json_format:
|
||||
time: "%START_TIME%"
|
||||
protocol: "%PROTOCOL%"
|
||||
duration: "%DURATION%"
|
||||
request_method: "%REQ(:METHOD)%"
|
||||
request_host: "%REQ(HOST)%"
|
||||
path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
|
||||
response_flags: "%RESPONSE_FLAGS%"
|
||||
route_name: "%ROUTE_NAME%"
|
||||
upstream_host: "%UPSTREAM_HOST%"
|
||||
upstream_cluster: "%UPSTREAM_CLUSTER%"
|
||||
upstream_local_address: "%UPSTREAM_LOCAL_ADDRESS%"
|
||||
path: "/tmp/access.log"
|
||||
clusters:
|
||||
- name: marketing
|
||||
connect_timeout: 0.25s
|
||||
type: logical_dns
|
||||
type: strict_dns
|
||||
lb_policy: round_robin
|
||||
hosts:
|
||||
- socket_address:
|
||||
@ -45,7 +67,7 @@ static_resources:
|
||||
port_value: 80
|
||||
- name: locations
|
||||
connect_timeout: 0.25s
|
||||
type: logical_dns
|
||||
type: strict_dns
|
||||
lb_policy: round_robin
|
||||
hosts:
|
||||
- socket_address:
|
||||
|
@ -1,4 +1,4 @@
|
||||
ç{{- if .Values.ingress.enabled -}}
|
||||
{{- if .Values.ingress.enabled -}}
|
||||
{{- $ingressPath := include "pathBase" . -}}
|
||||
{{- $serviceName := .Values.app.svc.webmarketingapigw -}}
|
||||
|
||||
|
@ -23,44 +23,76 @@ static_resources:
|
||||
domains:
|
||||
- "*"
|
||||
routes:
|
||||
- match:
|
||||
- name: "c-short"
|
||||
match:
|
||||
prefix: "/c/"
|
||||
route:
|
||||
auto_host_rewrite: true
|
||||
prefix_rewrite: "/catalog-api/"
|
||||
cluster: catalog
|
||||
- match:
|
||||
- name: "c-long"
|
||||
match:
|
||||
prefix: "/catalog-api/"
|
||||
route:
|
||||
auto_host_rewrite: true
|
||||
cluster: catalog
|
||||
- match:
|
||||
- name: "o-short"
|
||||
match:
|
||||
prefix: "/o/"
|
||||
route:
|
||||
auto_host_rewrite: true
|
||||
prefix_rewrite: "/ordering-api/"
|
||||
cluster: ordering
|
||||
- match:
|
||||
- name: "o-long"
|
||||
match:
|
||||
prefix: "/ordering-api/"
|
||||
route:
|
||||
auto_host_rewrite: true
|
||||
cluster: ordering
|
||||
- match:
|
||||
- name: "b-short"
|
||||
match:
|
||||
prefix: "/b/"
|
||||
route:
|
||||
auto_host_rewrite: true
|
||||
prefix_rewrite: "/basket-api/"
|
||||
cluster: basket
|
||||
- match:
|
||||
- name: "b-long"
|
||||
match:
|
||||
prefix: "/basket-api/"
|
||||
route:
|
||||
auto_host_rewrite: true
|
||||
cluster: basket
|
||||
- match:
|
||||
- name: "agg"
|
||||
match:
|
||||
prefix: "/"
|
||||
route:
|
||||
auto_host_rewrite: true
|
||||
prefix_rewrite: "/"
|
||||
cluster: shoppingagg
|
||||
http_filters:
|
||||
- name: envoy.router
|
||||
access_log:
|
||||
- name: envoy.file_access_log
|
||||
filter:
|
||||
not_health_check_filter: {}
|
||||
config:
|
||||
json_format:
|
||||
time: "%START_TIME%"
|
||||
protocol: "%PROTOCOL%"
|
||||
duration: "%DURATION%"
|
||||
request_method: "%REQ(:METHOD)%"
|
||||
request_host: "%REQ(HOST)%"
|
||||
path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
|
||||
response_flags: "%RESPONSE_FLAGS%"
|
||||
route_name: "%ROUTE_NAME%"
|
||||
upstream_host: "%UPSTREAM_HOST%"
|
||||
upstream_cluster: "%UPSTREAM_CLUSTER%"
|
||||
upstream_local_address: "%UPSTREAM_LOCAL_ADDRESS%"
|
||||
path: "/tmp/access.log"
|
||||
clusters:
|
||||
- name: shoppingagg
|
||||
connect_timeout: 0.25s
|
||||
type: logical_dns
|
||||
type: strict_dns
|
||||
lb_policy: round_robin
|
||||
hosts:
|
||||
- socket_address:
|
||||
@ -68,7 +100,7 @@ static_resources:
|
||||
port_value: 80
|
||||
- name: catalog
|
||||
connect_timeout: 0.25s
|
||||
type: logical_dns
|
||||
type: strict_dns
|
||||
lb_policy: round_robin
|
||||
hosts:
|
||||
- socket_address:
|
||||
@ -76,7 +108,7 @@ static_resources:
|
||||
port_value: 80
|
||||
- name: basket
|
||||
connect_timeout: 0.25s
|
||||
type: logical_dns
|
||||
type: strict_dns
|
||||
lb_policy: round_robin
|
||||
hosts:
|
||||
- socket_address:
|
||||
@ -84,7 +116,7 @@ static_resources:
|
||||
port_value: 80
|
||||
- name: ordering
|
||||
connect_timeout: 0.25s
|
||||
type: logical_dns
|
||||
type: strict_dns
|
||||
lb_policy: round_robin
|
||||
hosts:
|
||||
- socket_address:
|
||||
|
@ -21,6 +21,10 @@ spec:
|
||||
labels:
|
||||
app: {{ template "webspa.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
{{ if .Values.inf.mesh.enabled -}}
|
||||
annotations:
|
||||
linkerd.io/inject: enabled
|
||||
{{- end }}
|
||||
spec:
|
||||
{{ if .Values.inf.registry -}}
|
||||
imagePullSecrets:
|
||||
|
@ -26,7 +26,6 @@
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="3.0.1-dev-00099" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.2-dev-00824" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="$(Swashbuckle_AspNetCore)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="3.0.0-rc1.19456.10" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.0.0-rc1.19457.4" />
|
||||
<PackageReference Include="System.Net.Http.WinHttpHandler" Version="4.6.0-rc1.19456.4" />
|
||||
</ItemGroup>
|
||||
|
@ -3,7 +3,6 @@ using System.Threading.Tasks;
|
||||
using System;
|
||||
using Grpc.Core;
|
||||
using Serilog;
|
||||
using Polly;
|
||||
using Grpc.Net.Client;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
||||
@ -30,11 +29,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
||||
|
||||
try
|
||||
{
|
||||
return await Policy
|
||||
.Handle<Exception>(ex => true)
|
||||
.WaitAndRetryAsync(5, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (e, t) => Log.Warning("Retrying the call to urlGrpc ={@urlGrpc}, BaseAddress={@BaseAddress}, errorMessage={@message}", urlGrpc, channel.Target, e.Message))
|
||||
.ExecuteAsync(() => func(channel))
|
||||
;
|
||||
return await func(channel);
|
||||
}
|
||||
catch (RpcException e)
|
||||
{
|
||||
@ -46,8 +41,6 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
||||
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", false);
|
||||
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2Support", false);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static async Task CallService(string urlGrpc, Func<GrpcChannel, Task> func)
|
||||
@ -68,11 +61,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
||||
|
||||
try
|
||||
{
|
||||
await Policy
|
||||
.Handle<Exception>(ex => true)
|
||||
.WaitAndRetryAsync(5, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (e, t) => Log.Warning("Retrying the call to urlGrpc ={@urlGrpc}, BaseAddress={@BaseAddress}, errorMessage={@message}", urlGrpc, channel.Target, e.Message))
|
||||
.ExecuteAsync(() => func(channel))
|
||||
;
|
||||
await func(channel);
|
||||
}
|
||||
catch (RpcException e)
|
||||
{
|
||||
|
@ -14,12 +14,9 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Polly;
|
||||
using Polly.Extensions.Http;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
||||
{
|
||||
@ -184,41 +181,19 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
||||
services
|
||||
.AddHttpClient<IBasketService, BasketService>()
|
||||
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
|
||||
.AddPolicyHandler(GetRetryPolicy())
|
||||
.AddPolicyHandler(GetCircuitBreakerPolicy())
|
||||
.AddDevspacesSupport();
|
||||
|
||||
services.AddHttpClient<ICatalogService, CatalogService>()
|
||||
.AddPolicyHandler(GetRetryPolicy())
|
||||
.AddPolicyHandler(GetCircuitBreakerPolicy())
|
||||
.AddDevspacesSupport();
|
||||
|
||||
services.AddHttpClient<IOrderApiClient, OrderApiClient>()
|
||||
.AddPolicyHandler(GetRetryPolicy())
|
||||
.AddPolicyHandler(GetCircuitBreakerPolicy())
|
||||
.AddDevspacesSupport();
|
||||
|
||||
services.AddHttpClient<IOrderingService, OrderingService>()
|
||||
.AddPolicyHandler(GetRetryPolicy())
|
||||
.AddPolicyHandler(GetCircuitBreakerPolicy())
|
||||
.AddDevspacesSupport();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
|
||||
{
|
||||
return HttpPolicyExtensions
|
||||
.HandleTransientHttpError()
|
||||
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
|
||||
.WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
|
||||
}
|
||||
|
||||
private static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
|
||||
{
|
||||
return HttpPolicyExtensions
|
||||
.HandleTransientHttpError()
|
||||
.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,7 @@
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
using Grpc.Core;
|
||||
using Serilog;
|
||||
using Polly;
|
||||
using Grpc.Net.Client;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
|
||||
@ -30,11 +28,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
|
||||
|
||||
try
|
||||
{
|
||||
return await Policy
|
||||
.Handle<Exception>(ex => true)
|
||||
.WaitAndRetryAsync(5, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (e, t) => Log.Warning("Retrying the call to urlGrpc ={@urlGrpc}, BaseAddress={@BaseAddress}, errorMessage={@message}", urlGrpc, channel.Target, e.Message))
|
||||
.ExecuteAsync(() => func(channel))
|
||||
;
|
||||
return await func(channel);
|
||||
}
|
||||
catch (RpcException e)
|
||||
{
|
||||
@ -68,11 +62,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
|
||||
|
||||
try
|
||||
{
|
||||
await Policy
|
||||
.Handle<Exception>(ex => true)
|
||||
.WaitAndRetryAsync(5, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (e, t) => Log.Warning("Retrying the call to urlGrpc ={@urlGrpc}, BaseAddress={@BaseAddress}, errorMessage={@message}", urlGrpc, channel.Target, e.Message))
|
||||
.ExecuteAsync(() => func(channel))
|
||||
;
|
||||
await func(channel);
|
||||
}
|
||||
catch (RpcException e)
|
||||
{
|
||||
|
@ -15,13 +15,9 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Polly;
|
||||
using Polly.Extensions.Http;
|
||||
using Swashbuckle.AspNetCore.Swagger;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator
|
||||
{
|
||||
@ -188,44 +184,22 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator
|
||||
|
||||
services.AddHttpClient<IBasketService, BasketService>()
|
||||
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
|
||||
.AddPolicyHandler(GetRetryPolicy())
|
||||
.AddPolicyHandler(GetCircuitBreakerPolicy())
|
||||
.AddDevspacesSupport();
|
||||
|
||||
services.AddHttpClient<ICatalogService, CatalogService>()
|
||||
.AddPolicyHandler(GetRetryPolicy())
|
||||
.AddPolicyHandler(GetCircuitBreakerPolicy())
|
||||
.AddDevspacesSupport();
|
||||
|
||||
services.AddHttpClient<IOrderApiClient, OrderApiClient>()
|
||||
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
|
||||
.AddPolicyHandler(GetRetryPolicy())
|
||||
.AddPolicyHandler(GetCircuitBreakerPolicy())
|
||||
.AddDevspacesSupport();
|
||||
|
||||
services.AddHttpClient<IOrderingService, OrderingService>()
|
||||
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
|
||||
.AddPolicyHandler(GetRetryPolicy())
|
||||
.AddPolicyHandler(GetCircuitBreakerPolicy())
|
||||
.AddDevspacesSupport();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
|
||||
{
|
||||
return HttpPolicyExtensions
|
||||
.HandleTransientHttpError()
|
||||
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
|
||||
.WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
|
||||
|
||||
}
|
||||
|
||||
static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
|
||||
{
|
||||
return HttpPolicyExtensions
|
||||
.HandleTransientHttpError()
|
||||
.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,36 +1,4 @@
|
||||
<!--<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>$(NetCoreTargetVersion)</TargetFramework>
|
||||
<AssemblyName>Web.Shopping.HttpAggregator</AssemblyName>
|
||||
<RootNamespace>Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator</RootNamespace>
|
||||
<DockerComposeProjectPath>..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
|
||||
<GenerateErrorForMissingTargetingPacks>false</GenerateErrorForMissingTargetingPacks>
|
||||
<IsTransformWebConfigDisabled>true</IsTransformWebConfigDisabled>
|
||||
<LangVersion>$(LangVersion)</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="wwwroot\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspNetCore.HealthChecks.Uris" Version="$(AspNetCore_HealthChecks_Uris)" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="$(AspNetCore_HealthChecks_UI_Client)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="$(Microsoft_AspNetCore_Diagnostics_HealthChecks)" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="$(Serilog_AspNetCore)" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="$(Serilog_Sinks_Console)" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="$(Swashbuckle_AspNetCore)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="$(Microsoft_Extensions_Http_Polly)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="$(Microsoft_AspNetCore_Authentication_JwtBearer)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\Devspaces.Support\Devspaces.Support.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>-->
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>$(NetCoreTargetVersion)</TargetFramework>
|
||||
@ -59,7 +27,6 @@
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="3.0.1-dev-00099" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.2-dev-00824" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="$(Swashbuckle_AspNetCore)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="3.0.0-rc1.19456.10" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.0.0-rc1.19457.4" />
|
||||
<PackageReference Include="System.Net.Http.WinHttpHandler" Version="4.6.0-rc1.19456.4" />
|
||||
</ItemGroup>
|
||||
|
@ -2,7 +2,6 @@ using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Services;
|
||||
using Microsoft.eShopOnContainers.WebMVC.ViewModels;
|
||||
using Polly.CircuitBreaker;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
@ -32,10 +31,9 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
||||
|
||||
return View(vm);
|
||||
}
|
||||
catch (BrokenCircuitException)
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Catch error when Basket.api is in circuit-opened mode
|
||||
HandleBrokenCircuitException();
|
||||
HandleException(ex);
|
||||
}
|
||||
|
||||
return View();
|
||||
@ -54,10 +52,9 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
||||
return RedirectToAction("Create", "Order");
|
||||
}
|
||||
}
|
||||
catch (BrokenCircuitException)
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Catch error when Basket.api is in circuit-opened mode
|
||||
HandleBrokenCircuitException();
|
||||
HandleException(ex);
|
||||
}
|
||||
|
||||
return View();
|
||||
@ -74,18 +71,18 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
||||
}
|
||||
return RedirectToAction("Index", "Catalog");
|
||||
}
|
||||
catch (BrokenCircuitException)
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Catch error when Basket.api is in circuit-opened mode
|
||||
HandleBrokenCircuitException();
|
||||
HandleException(ex);
|
||||
}
|
||||
|
||||
return RedirectToAction("Index", "Catalog", new { errorMsg = ViewBag.BasketInoperativeMsg });
|
||||
}
|
||||
|
||||
private void HandleBrokenCircuitException()
|
||||
private void HandleException(Exception ex)
|
||||
{
|
||||
ViewBag.BasketInoperativeMsg = "Basket Service is inoperative, please try later on. (Business Msg Due to Circuit-Breaker)";
|
||||
ViewBag.BasketInoperativeMsg = $"Basket Service is inoperative {ex.GetType().Name} - {ex.Message}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Services;
|
||||
using Microsoft.eShopOnContainers.WebMVC.ViewModels;
|
||||
using Polly.CircuitBreaker;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
||||
@ -47,9 +47,9 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
}
|
||||
catch (BrokenCircuitException)
|
||||
catch (Exception ex)
|
||||
{
|
||||
ModelState.AddModelError("Error", "It was not possible to create a new order, please try later on. (Business Msg Due to Circuit-Breaker)");
|
||||
ModelState.AddModelError("Error", $"It was not possible to create a new order, please try later on ({ex.GetType().Name} - {ex.Message})");
|
||||
}
|
||||
|
||||
return View("Create", model);
|
||||
|
@ -15,8 +15,6 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.IdentityModel.Logging;
|
||||
using Polly;
|
||||
using Polly.Extensions.Http;
|
||||
using StackExchange.Redis;
|
||||
using System;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
@ -146,7 +144,7 @@ namespace Microsoft.eShopOnContainers.WebMVC
|
||||
return services;
|
||||
}
|
||||
|
||||
// Adds all Http client services (like Service-Agents) using resilient Http requests based on HttpClient factory and Polly's policies
|
||||
// Adds all Http client services
|
||||
public static IServiceCollection AddHttpClientServices(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||
@ -162,32 +160,22 @@ namespace Microsoft.eShopOnContainers.WebMVC
|
||||
services.AddHttpClient<IBasketService, BasketService>()
|
||||
.SetHandlerLifetime(TimeSpan.FromMinutes(5)) //Sample. Default lifetime is 2 minutes
|
||||
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
|
||||
.AddPolicyHandler(GetRetryPolicy())
|
||||
.AddPolicyHandler(GetCircuitBreakerPolicy())
|
||||
.AddDevspacesSupport();
|
||||
|
||||
services.AddHttpClient<ICatalogService, CatalogService>()
|
||||
.AddPolicyHandler(GetRetryPolicy())
|
||||
.AddPolicyHandler(GetCircuitBreakerPolicy())
|
||||
.AddDevspacesSupport();
|
||||
|
||||
services.AddHttpClient<IOrderingService, OrderingService>()
|
||||
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
|
||||
.AddHttpMessageHandler<HttpClientRequestIdDelegatingHandler>()
|
||||
.AddPolicyHandler(GetRetryPolicy())
|
||||
.AddPolicyHandler(GetCircuitBreakerPolicy())
|
||||
.AddDevspacesSupport();
|
||||
|
||||
services.AddHttpClient<ICampaignService, CampaignService>()
|
||||
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
|
||||
.AddPolicyHandler(GetRetryPolicy())
|
||||
.AddPolicyHandler(GetCircuitBreakerPolicy())
|
||||
.AddDevspacesSupport();
|
||||
|
||||
services.AddHttpClient<ILocationService, LocationService>()
|
||||
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
|
||||
.AddPolicyHandler(GetRetryPolicy())
|
||||
.AddPolicyHandler(GetCircuitBreakerPolicy())
|
||||
.AddDevspacesSupport();
|
||||
|
||||
//add custom application services
|
||||
@ -235,19 +223,5 @@ namespace Microsoft.eShopOnContainers.WebMVC
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
|
||||
{
|
||||
return HttpPolicyExtensions
|
||||
.HandleTransientHttpError()
|
||||
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
|
||||
.WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
|
||||
}
|
||||
static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
|
||||
{
|
||||
return HttpPolicyExtensions
|
||||
.HandleTransientHttpError()
|
||||
.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Polly.CircuitBreaker;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.WebMVC.ViewComponents
|
||||
{
|
||||
@ -25,9 +24,8 @@ namespace Microsoft.eShopOnContainers.WebMVC.ViewComponents
|
||||
vm.ItemsCount = itemsInCart;
|
||||
return View(vm);
|
||||
}
|
||||
catch (BrokenCircuitException)
|
||||
catch
|
||||
{
|
||||
// Catch error when Basket.api is in circuit-opened mode
|
||||
ViewBag.IsBasketInoperative = true;
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Polly.CircuitBreaker;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.WebMVC.ViewComponents
|
||||
{
|
||||
@ -23,10 +22,9 @@ namespace Microsoft.eShopOnContainers.WebMVC.ViewComponents
|
||||
vm = await GetItemsAsync(user);
|
||||
return View(vm);
|
||||
}
|
||||
catch (BrokenCircuitException)
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Catch error when Basket.api is in circuit-opened mode
|
||||
ViewBag.BasketInoperativeMsg = "Basket Service is inoperative, please try later on. (Business Msg Due to Circuit-Breaker)";
|
||||
ViewBag.BasketInoperativeMsg = $"Basket Service is inoperative, please try later on. ({ex.GetType().Name} - {ex.Message}))";
|
||||
}
|
||||
|
||||
return View(vm);
|
||||
|
@ -31,7 +31,6 @@
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="$(Microsoft_AspNetCore_Diagnostics_HealthChecks)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.HealthChecks" Version="$(Microsoft_AspNetCore_HealthChecks)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="3.0.0-rc1.19456.10" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="3.0.0-rc1.19456.10" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.DataProtection.Redis" Version="2.2.0-preview3-35458" />
|
||||
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="16.0.461" />
|
||||
|
Loading…
x
Reference in New Issue
Block a user