Browse Source

Merge pull request #97 from abpframework/gterdem/yarp

eShopOnAbp: Switch Ocelot to YAG
pull/98/head
Galip Tolga Erdem 5 years ago
committed by GitHub
parent
commit
b405597113
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 43
      gateways/web-public/src/EShopOnAbp.WebPublicGateway/EShopOnAbpWebPublicGatewayModule.cs
  2. 1
      gateways/web-public/src/EShopOnAbp.WebPublicGateway/appsettings.json
  3. 113
      gateways/web-public/src/EShopOnAbp.WebPublicGateway/ocelot.json
  4. 100
      gateways/web-public/src/EShopOnAbp.WebPublicGateway/yarp.json
  5. 29
      gateways/web/src/EShopOnAbp.WebGateway/EShopOnAbpWebGatewayModule.cs
  6. 90
      gateways/web/src/EShopOnAbp.WebGateway/ocelot.json
  7. 86
      gateways/web/src/EShopOnAbp.WebGateway/yarp.json
  8. 7
      shared/EShopOnAbp.Shared.Hosting.Gateways/EShopOnAbp.Shared.Hosting.Gateways.csproj
  9. 12
      shared/EShopOnAbp.Shared.Hosting.Gateways/EShopOnAbpSharedHostingGatewaysModule.cs
  10. 6
      shared/EShopOnAbp.Shared.Hosting.Gateways/GatewayHostBuilderExtensions.cs
  11. 20
      shared/EShopOnAbp.Shared.Hosting.Gateways/OcelotConfiguration.cs
  12. 52
      shared/EShopOnAbp.Shared.Hosting.Gateways/YarpSwaggerUIBuilderExtensions.cs

43
gateways/web-public/src/EShopOnAbp.WebPublicGateway/EShopOnAbpWebPublicGatewayModule.cs

@ -1,12 +1,10 @@
using EShopOnAbp.Shared.Hosting.Gateways;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Ocelot.Middleware;
using System.Collections.Generic;
using System.Linq;
using EShopOnAbp.Shared.Hosting.AspNetCore;
using Microsoft.AspNetCore.Http;
using Volo.Abp;
using Volo.Abp.Modularity;
using Microsoft.AspNetCore.Rewrite;
@ -38,6 +36,9 @@ public class EShopOnAbpWebPublicGatewayModule : AbpModule
},
apiTitle: "WebPublic Gateway"
);
// context.Services.AddReverseProxy()
// .LoadFromConfig(configuration.GetSection("ReverseProxy"));
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
@ -52,35 +53,17 @@ public class EShopOnAbpWebPublicGatewayModule : AbpModule
app.UseCorrelationId();
app.UseAbpSerilogEnrichers();
app.UseSwagger();
app.UseSwaggerUI(options =>
{
var configuration = context.ServiceProvider.GetRequiredService<IConfiguration>();
var routes = configuration.GetSection("Routes").Get<List<OcelotConfiguration>>();
var routedServices = routes
.GroupBy(t => t.ServiceKey)
.Select(r => r.First())
.Distinct();
foreach (var config in routedServices)
{
var url =
$"{config.DownstreamScheme}://{config.DownstreamHostAndPorts.FirstOrDefault()?.Host}:{config.DownstreamHostAndPorts.FirstOrDefault()?.Port}";
if (!env.IsDevelopment())
{
url = $"https://{config.DownstreamHostAndPorts.FirstOrDefault()?.Host}";
}
options.SwaggerEndpoint($"{url}/swagger/v1/swagger.json", $"{config.ServiceKey} API");
options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]);
options.OAuthClientSecret(configuration["AuthServer:SwaggerClientSecret"]);
}
});
app.ConfigureSwaggerUIWithYarp(context);
app.UseRewriter(new RewriteOptions()
// Regex for "", "/" and "" (whitespace)
.AddRedirect("^(|\\|\\s+)$", "/swagger"));
app.UseOcelot().Wait();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("", ctx => ctx.Response.WriteAsync("YAG"));
endpoints.MapReverseProxy();
});
}
}

1
gateways/web-public/src/EShopOnAbp.WebPublicGateway/appsettings.json

@ -17,7 +17,6 @@
}
},
"AllowedHosts": "*",
"Redis": {
"Configuration": "localhost:6379"
},

113
gateways/web-public/src/EShopOnAbp.WebPublicGateway/ocelot.json

@ -1,113 +0,0 @@
{
"GlobalConfiguration": {
"BaseUrl": "https://localhost:44373"
},
"Routes": [
{
"ServiceKey": "Account Service",
"DownstreamPathTemplate": "/api/account/{everything}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44330
}
],
"UpstreamPathTemplate": "/api/account/{everything}",
"UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
},
{
"ServiceKey": "Administration Service",
"DownstreamPathTemplate": "/api/abp/{everything}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44353
}
],
"UpstreamPathTemplate": "/api/abp/{everything}",
"UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 3000,
"TimeoutValue": 2500
}
},
{
"ServiceKey": "Catalog Service",
"DownstreamPathTemplate": "/api/catalog/{everything}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44354
}
],
"UpstreamPathTemplate": "/api/catalog/{everything}",
"UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 3000,
"TimeoutValue": 2500
}
},
{
"ServiceKey": "Catalog Service",
"DownstreamPathTemplate": "/product-images/{everything}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44354
}
],
"UpstreamPathTemplate": "/product-images/{everything}",
"UpstreamHttpMethod": [ "Get" ]
},
{
"ServiceKey": "Basket Service",
"DownstreamPathTemplate": "/api/basket/{everything}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44355
}
],
"UpstreamPathTemplate": "/api/basket/{everything}",
"UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 3000,
"TimeoutValue": 2500
}
},
{
"ServiceKey": "Ordering Service",
"DownstreamPathTemplate": "/api/ordering/{everything}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44356
}
],
"UpstreamPathTemplate": "/api/ordering/{everything}",
"UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
},
{
"ServiceKey": "Payment Service",
"DownstreamPathTemplate": "/api/payment/{everything}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44357
}
],
"UpstreamPathTemplate": "/api/payment/{everything}",
"UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
}
]
}

100
gateways/web-public/src/EShopOnAbp.WebPublicGateway/yarp.json

@ -0,0 +1,100 @@
{
"ReverseProxy": {
"Routes": {
"Account Service": {
"ClusterId": "account-cluster",
"Match": {
"Path": "/api/account/{**everything}"
}
},
"Administration Service": {
"ClusterId": "administration-cluster",
"Match": {
"Path": "/api/abp/{**everything}"
}
},
"Catalog Service": {
"ClusterId": "catalog-cluster",
"Match": {
"Path": "/api/catalog/{**everything}"
}
},
"Basket Service": {
"ClusterId": "basket-cluster",
"Match": {
"Path": "/api/basket/{**everything}"
}
},
"Ordering Service": {
"ClusterId": "ordering-cluster",
"Match": {
"Path": "/api/ordering/{**everything}"
}
},
"Payment Service": {
"ClusterId": "payment-cluster",
"Match": {
"Path": "/api/payment/{**everything}"
}
},
"product-picture-route": {
"ClusterId": "product-picture-cluster",
"Match": {
"Path": "/product-images/{**everything}",
"Methods" : [ "GET" ]
}
}
},
"Clusters": {
"account-cluster": {
"Destinations": {
"destination1": {
"Address": "https://localhost:44330"
}
}
},
"administration-cluster": {
"Destinations": {
"destination1": {
"Address": "https://localhost:44353"
}
}
},
"catalog-cluster": {
"Destinations": {
"destination1": {
"Address": "https://localhost:44354"
}
}
},
"product-picture-cluster": {
"Destinations": {
"destination1": {
"Address": "https://localhost:44354"
}
}
},
"basket-cluster": {
"Destinations": {
"destination1": {
"Address": "https://localhost:44355"
}
}
},
"ordering-cluster": {
"Destinations": {
"destination1": {
"Address": "https://localhost:44356"
}
}
},
"payment-cluster": {
"Destinations": {
"destination1": {
"Address": "https://localhost:44357"
}
}
}
}
}
}

29
gateways/web/src/EShopOnAbp.WebGateway/EShopOnAbpWebGatewayModule.cs

@ -4,7 +4,6 @@ using Microsoft.AspNetCore.Cors;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Ocelot.Middleware;
using System;
using System.Collections.Generic;
using System.Linq;
@ -71,39 +70,15 @@ public class EShopOnAbpWebGatewayModule : AbpModule
{
app.UseDeveloperExceptionPage();
}
app.UseCorrelationId();
app.UseAbpSerilogEnrichers();
app.UseCors();
app.UseSwagger();
app.UseSwaggerUI(options =>
{
var configuration = context.ServiceProvider.GetRequiredService<IConfiguration>();
var routes = configuration.GetSection("Routes").Get<List<OcelotConfiguration>>();
var routedServices = routes
.GroupBy(t => t.ServiceKey)
.Select(r => r.First())
.Distinct();
foreach (var config in routedServices)
{
var url =
$"{config.DownstreamScheme}://{config.DownstreamHostAndPorts.FirstOrDefault()?.Host}:{config.DownstreamHostAndPorts.FirstOrDefault()?.Port}";
if (!env.IsDevelopment())
{
url = $"https://{config.DownstreamHostAndPorts.FirstOrDefault()?.Host}";
}
options.SwaggerEndpoint($"{url}/swagger/v1/swagger.json", $"{config.ServiceKey} API");
options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]);
options.OAuthClientSecret(configuration["AuthServer:SwaggerClientSecret"]);
}
});
app.ConfigureSwaggerUIWithYarp(context);
app.UseRewriter(new RewriteOptions()
// Regex for "", "/" and "" (whitespace)
.AddRedirect("^(|\\|\\s+)$", "/swagger"));
app.UseOcelot().Wait();
// app.UseOcelot().Wait();
}
}

90
gateways/web/src/EShopOnAbp.WebGateway/ocelot.json

@ -1,90 +0,0 @@
{
"GlobalConfiguration": {
"BaseUrl": "https://localhost:44372"
},
"Routes": [
{
"ServiceKey": "Identity Service",
"DownstreamPathTemplate": "/api/identity/{everything}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44351
}
],
"UpstreamPathTemplate": "/api/identity/{everything}",
"UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
},
{
"ServiceKey": "Account Service",
"DownstreamPathTemplate": "/api/account/{everything}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44330
}
],
"UpstreamPathTemplate": "/api/account/{everything}",
"UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
},
{
"ServiceKey": "Administration Service",
"DownstreamPathTemplate": "/api/abp/{everything}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44353
}
],
"UpstreamPathTemplate": "/api/abp/{everything}",
"UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 5000,
"TimeoutValue": 2500
}
},
{
"ServiceKey": "Administration Service",
"DownstreamPathTemplate": "/api/feature-management/{everything}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44353
}
],
"UpstreamPathTemplate": "/api/feature-management/{everything}",
"UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
},
{
"ServiceKey": "Administration Service",
"DownstreamPathTemplate": "/api/permission-management/{everything}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44353
}
],
"UpstreamPathTemplate": "/api/permission-management/{everything}",
"UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
},
{
"ServiceKey": "Administration Service",
"DownstreamPathTemplate": "/api/setting-management/{everything}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44353
}
],
"UpstreamPathTemplate": "/api/setting-management/{everything}",
"UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
}
]
}

86
gateways/web/src/EShopOnAbp.WebGateway/yarp.json

@ -0,0 +1,86 @@
{
"ReverseProxy": {
"Routes": {
"Account Service": {
"ClusterId": "account-cluster",
"Match": {
"Path": "/api/account/{**everything}"
}
},
"Identity Service": {
"ClusterId": "identity-cluster",
"Match": {
"Path": "/api/identity/{**everything}"
}
},
"Administration Service": {
"ClusterId": "administration-cluster",
"Match": {
"Path": "/api/abp/{**everything}"
}
},
"feature-management-route": {
"ClusterId": "feature-management-cluster",
"Match": {
"Path": "/api/feature-management/{**everything}"
}
},
"permission-management-route": {
"ClusterId": "permission-management-cluster",
"Match": {
"Path": "/api/permission-management/{**everything}"
}
},
"setting-management-route": {
"ClusterId": "setting-management-cluster",
"Match": {
"Path": "/api/setting-management/{**everything}"
}
}
},
"Clusters": {
"account-cluster": {
"Destinations": {
"destination1": {
"Address": "https://localhost:44330"
}
}
},
"identity-cluster": {
"Destinations": {
"destination1": {
"Address": "https://localhost:44351"
}
}
},
"administration-cluster": {
"Destinations": {
"destination1": {
"Address": "https://localhost:44353"
}
}
},
"feature-management-cluster": {
"Destinations": {
"destination1": {
"Address": "https://localhost:44353"
}
}
},
"permission-management-cluster": {
"Destinations": {
"destination1": {
"Address": "https://localhost:44353"
}
}
},
"setting-management-cluster": {
"Destinations": {
"destination1": {
"Address": "https://localhost:44353"
}
}
}
}
}
}

7
shared/EShopOnAbp.Shared.Hosting.Gateways/EShopOnAbp.Shared.Hosting.Gateways.csproj

@ -5,12 +5,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Ocelot" Version="18.0.0" />
<PackageReference Include="Ocelot.Provider.Polly" Version="18.0.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy" Version="5.1.2" />
<PackageReference Include="Yarp.ReverseProxy" Version="1.0.0" />
</ItemGroup>
<ItemGroup>

12
shared/EShopOnAbp.Shared.Hosting.Gateways/EShopOnAbpSharedHostingGatewaysModule.cs

@ -1,24 +1,20 @@
using EShopOnAbp.Shared.Hosting.AspNetCore;
using Microsoft.Extensions.DependencyInjection;
using Ocelot.DependencyInjection;
using Ocelot.Provider.Polly;
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy;
using Volo.Abp.Modularity;
namespace EShopOnAbp.Shared.Hosting.Gateways
{
[DependsOn(
typeof(EShopOnAbpSharedHostingAspNetCoreModule),
typeof(AbpAspNetCoreMvcUiMultiTenancyModule)
typeof(EShopOnAbpSharedHostingAspNetCoreModule)
)]
public class EShopOnAbpSharedHostingGatewaysModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
context.Services.AddOcelot(configuration)
.AddPolly();
context.Services.AddReverseProxy()
.LoadFromConfig(configuration.GetSection("ReverseProxy"));
}
}
}

6
shared/EShopOnAbp.Shared.Hosting.Gateways/GatewayHostBuilderExtensions.cs

@ -4,18 +4,18 @@ namespace Microsoft.Extensions.Hosting;
public static class AbpHostingHostBuilderExtensions
{
public const string AppOcelotJsonPath = "ocelot.json";
public const string AppYarpJsonPath = "yarp.json";
public static IHostBuilder AddOcelotJson(
this IHostBuilder hostBuilder,
bool optional = true,
bool reloadOnChange = true,
string path = AppOcelotJsonPath)
string path = AppYarpJsonPath)
{
return hostBuilder.ConfigureAppConfiguration((_, builder) =>
{
builder.AddJsonFile(
path: AppOcelotJsonPath,
path: AppYarpJsonPath,
optional: optional,
reloadOnChange: reloadOnChange
);

20
shared/EShopOnAbp.Shared.Hosting.Gateways/OcelotConfiguration.cs

@ -1,20 +0,0 @@
using System.Collections.Generic;
namespace EShopOnAbp.Shared.Hosting.Gateways
{
public class OcelotConfiguration
{
public string ServiceKey { get; set; }
public string DownstreamPathTemplate { get; set; }
public string DownstreamScheme { get; set; }
public string UpstreamPathTemplate { get; set; }
public List<string> UpstreamHttpMethod { get; set; }
public List<HostAndPort> DownstreamHostAndPorts { get; set; }
}
public class HostAndPort
{
public string Host { get; set; }
public int Port { get; set; }
}
}

52
shared/EShopOnAbp.Shared.Hosting.Gateways/YarpSwaggerUIBuilderExtensions.cs

@ -0,0 +1,52 @@
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Volo.Abp;
using Yarp.ReverseProxy.Configuration;
namespace EShopOnAbp.Shared.Hosting.Gateways;
public static class YarpSwaggerUIBuilderExtensions
{
public static IApplicationBuilder ConfigureSwaggerUIWithYarp(this IApplicationBuilder app,
ApplicationInitializationContext context)
{
app.UseSwagger();
app.UseSwaggerUI(options =>
{
var configuration = context.ServiceProvider.GetRequiredService<IConfiguration>();
var logger = context.ServiceProvider.GetRequiredService<ILogger<ApplicationInitializationContext>>();
var proxyConfigProvider = context.ServiceProvider.GetRequiredService<IProxyConfigProvider>();
var yarpConfig = proxyConfigProvider.GetConfig();
var routedClusters = yarpConfig.Clusters
.SelectMany(t => t.Destinations,
(clusterId, destination) => new {clusterId.ClusterId, destination.Value});
var groupedClusters = routedClusters
.GroupBy(q => q.Value.Address)
.Select(t => t.First())
.Distinct()
.ToList();
foreach (var clusterGroup in groupedClusters)
{
var routeConfig = yarpConfig.Routes.FirstOrDefault(q =>
q.ClusterId == clusterGroup.ClusterId);
if (routeConfig == null)
{
logger.LogWarning($"Swagger UI: Couldn't find route configuration for {clusterGroup.ClusterId}...");
continue;
}
options.SwaggerEndpoint($"{clusterGroup.Value.Address}/swagger/v1/swagger.json", $"{routeConfig.RouteId} API");
options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]);
options.OAuthClientSecret(configuration["AuthServer:SwaggerClientSecret"]);
}
});
return app;
}
}
Loading…
Cancel
Save