Browse Source

apigateway host create an basic endpoint

pull/84/head
cKey 5 years ago
parent
commit
5ab4ab344e
  1. 3
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Domain.Shared/LINGYUN/ApiGateway/Localization/DomainShared/en.json
  2. 3
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Domain.Shared/LINGYUN/ApiGateway/Localization/DomainShared/zh-Hans.json
  3. 33
      aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/ApiGatewayHostModule.cs
  4. 51
      aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/Controllers/ApiGatewayController.cs
  5. 6
      aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/LINGYUN.ApiGateway.Host.csproj
  6. 10
      aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/Localization/Host/en.json
  7. 10
      aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/Localization/Host/zh-Hans.json
  8. 22
      aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/Utils/ILoadBalancerFinder.cs
  9. 58
      aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/Utils/LoadBalancerFinder.cs
  10. 16
      vueJs/src/api/apigateway.ts
  11. 3
      vueJs/src/lang/en.ts
  12. 3
      vueJs/src/lang/zh.ts
  13. 37
      vueJs/src/views/admin/apigateway/components/AggregateRouteCreateOrEditForm.vue
  14. 21
      vueJs/src/views/admin/apigateway/components/GlobalCreateOrEditForm.vue
  15. 25
      vueJs/src/views/admin/apigateway/components/RouteCreateOrEditForm.vue

3
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Domain.Shared/LINGYUN/ApiGateway/Localization/DomainShared/en.json

@ -38,9 +38,6 @@
"UseTracing": "Http track",
"LoadBalancer": "Load balancer",
"LoadWay": "Balancer type",
"LeastConnection": "Least connection",
"RoundRobin": "Round robin",
"NoLoadBalance": "No load balance",
"ServiceDiscovery": "Service discovery",
"DiscoveryType": "Service type",
"Host": "Host",

3
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Domain.Shared/LINGYUN/ApiGateway/Localization/DomainShared/zh-Hans.json

@ -38,9 +38,6 @@
"UseTracing": "HTTP追踪",
"LoadBalancer": "负载均衡",
"LoadWay": "负载方式",
"LeastConnection": "总是空闲服务器",
"RoundRobin": "服务器轮询",
"NoLoadBalance": "发往首个服务器",
"ServiceDiscovery": "服务发现",
"DiscoveryType": "实例类型",
"Host": "主机地址",

33
aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/ApiGatewayHostModule.cs

@ -1,7 +1,9 @@
using DotNetCore.CAP;
using LINGYUN.Abp.EventBus.CAP;
using LINGYUN.ApiGateway.Localization;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Caching.StackExchangeRedis;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
@ -22,9 +24,11 @@ using Volo.Abp.Caching;
using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.Http.Client.IdentityModel;
using Volo.Abp.IdentityModel;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.Security.Claims;
using Volo.Abp.Security.Encryption;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.ApiGateway
{
@ -125,12 +129,39 @@ namespace LINGYUN.ApiGateway
}
});
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<ApiGatewayHostModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Languages.Add(new LanguageInfo("en", "en", "English"));
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
options.Resources
.Get<ApiGatewayResource>()
.AddVirtualJson("/Localization/Host");
});
Configure<IdentityModelHttpRequestMessageOptions>(options =>
{
// See https://github.com/abpframework/abp/pull/4564
options.ConfigureHttpRequestMessage = (requestMessage) => { };
});
var mvcBuilder = context.Services.AddMvc();
mvcBuilder.AddApplicationPart(typeof(ApiGatewayHostModule).Assembly);
Configure<AbpEndpointRouterOptions>(options =>
{
options.EndpointConfigureActions.Add(endpointContext =>
{
endpointContext.Endpoints.MapControllerRoute("defaultWithArea", "{area}/{controller=Home}/{action=Index}/{id?}");
endpointContext.Endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
});
});
context.Services
.AddOcelot()
.AddPolly()
@ -142,6 +173,8 @@ namespace LINGYUN.ApiGateway
var app = context.GetApplicationBuilder();
app.UseAuditing();
app.UseRouting();
app.UseConfiguredEndpoints();
// 启用ws协议
app.UseWebSockets();
app.UseOcelot().Wait();

51
aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/Controllers/ApiGatewayController.cs

@ -0,0 +1,51 @@
using LINGYUN.ApiGateway.Utils;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Ocelot.LoadBalancer.LoadBalancers;
using Ocelot.Multiplexer;
using System;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
namespace LINGYUN.ApiGateway.Controllers
{
[RemoteService(Name = ApiGatewayConsts.RemoteServiceName)]
[Area("ApiGateway")]
[Route("api/ApiGateway/Basic")]
public class ApiGatewayController : Controller
{
protected IServiceProvider ServiceProvider { get; }
protected ILoadBalancerFinder LoadBalancerFinder { get; }
public ApiGatewayController(
IServiceProvider serviceProvider,
ILoadBalancerFinder loadBalancerFinder)
{
ServiceProvider = serviceProvider;
LoadBalancerFinder = loadBalancerFinder;
}
[HttpGet]
[Route("Aggregators")]
public Task<JsonResult> GetAggregatorsAsync()
{
var aggregators = ServiceProvider.GetServices<IDefinedAggregator>();
var aggregatorDtos = new ListResultDto<string>(aggregators.Select(agg => agg.GetType().Name).ToList());
return Task.FromResult(Json(aggregatorDtos));
}
[HttpGet]
[Route("LoadBalancers")]
public async Task<JsonResult> GetLoadBalancersAsync()
{
var loadBalancers = await LoadBalancerFinder.GetLoadBalancersAsync();
var loadBalancerDtos = new ListResultDto<LoadBalancerDescriptor>(loadBalancers);
return Json(loadBalancerDtos);
}
}
}

6
aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/LINGYUN.ApiGateway.Host.csproj

@ -5,6 +5,11 @@
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Localization\Host\en.json" />
<EmbeddedResource Include="Localization\Host\zh-Hans.json" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="DotNetCore.CAP.Dashboard" Version="3.0.4" />
<PackageReference Include="DotNetCore.CAP.RabbitMQ" Version="3.0.4" />
@ -20,6 +25,7 @@
<PackageReference Include="Volo.Abp.Autofac" Version="3.1.0" />
<PackageReference Include="Volo.Abp.AspNetCore" Version="3.1.0" />
<PackageReference Include="Volo.Abp.AutoMapper" Version="3.1.0" />
<PackageReference Include="Volo.Abp.Ddd.Application" Version="3.1.0" />
<PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="3.1.0" />
<PackageReference Include="Volo.Abp.Http.Client.IdentityModel" Version="3.1.0" />
</ItemGroup>

10
aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/Localization/Host/en.json

@ -0,0 +1,10 @@
{
"culture": "en",
"texts": {
"NoLoadBalancer": "No Load balancer",
"RoundRobin": "Round robin",
"LeastConnection": "Least connection",
"CookieStickySessions": "Cookie sticky sessions",
"CustomLoadBalancer": "Custom load balancer - {0}"
}
}

10
aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/Localization/Host/zh-Hans.json

@ -0,0 +1,10 @@
{
"culture": "zh-Hans",
"texts": {
"NoLoadBalancer": "无负载均衡",
"RoundRobin": "服务器轮询",
"LeastConnection": "总是空闲服务器",
"CookieStickySessions": "粘性会话类型",
"CustomLoadBalancer": "自定义负载均衡器 - {0}"
}
}

22
aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/Utils/ILoadBalancerFinder.cs

@ -0,0 +1,22 @@
using Microsoft.Extensions.Localization;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace LINGYUN.ApiGateway.Utils
{
public interface ILoadBalancerFinder
{
Task<List<LoadBalancerDescriptor>> GetLoadBalancersAsync();
}
public class LoadBalancerDescriptor
{
public string Type { get; }
public string DisplayName { get; }
public LoadBalancerDescriptor(string type, string displayName)
{
Type = type;
DisplayName = displayName;
}
}
}

58
aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/Utils/LoadBalancerFinder.cs

@ -0,0 +1,58 @@
using LINGYUN.ApiGateway.Localization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Ocelot.LoadBalancer.LoadBalancers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.ApiGateway.Utils
{
public class LoadBalancerFinder : ILoadBalancerFinder, ISingletonDependency
{
private Lazy<List<LoadBalancerDescriptor>> lazyLoadBalancers;
protected List<LoadBalancerDescriptor> LoadBalancers => lazyLoadBalancers.Value;
protected IServiceProvider ServiceProvider { get; }
protected IStringLocalizer Localizer { get; }
public LoadBalancerFinder(
IServiceProvider serviceProvider,
IStringLocalizer<ApiGatewayResource> localizer)
{
Localizer = localizer;
ServiceProvider = serviceProvider;
lazyLoadBalancers = new Lazy<List<LoadBalancerDescriptor>>(() => FindLocalLoadBalancers());
}
public Task<List<LoadBalancerDescriptor>> GetLoadBalancersAsync()
{
return Task.FromResult(LoadBalancers);
}
protected List<LoadBalancerDescriptor> FindLocalLoadBalancers()
{
List<LoadBalancerDescriptor> loadBalancers = new List<LoadBalancerDescriptor>
{
new LoadBalancerDescriptor(typeof(NoLoadBalancer).Name, Localizer["NoLoadBalancer"]),
new LoadBalancerDescriptor(typeof(RoundRobin).Name, Localizer["RoundRobin"]),
new LoadBalancerDescriptor(typeof(LeastConnection).Name, Localizer["LeastConnection"]),
new LoadBalancerDescriptor(typeof(CookieStickySessions).Name, Localizer["CookieStickySessions"])
};
var loadBalancerCreators = ServiceProvider.GetServices<ILoadBalancerCreator>();
loadBalancerCreators = loadBalancerCreators
.Where(lbc => !loadBalancers.Any(l => l.Type.Equals(lbc.Type)))
.ToArray();
foreach(var defintedLoadBalancerCreator in loadBalancerCreators)
{
loadBalancers.Add(new LoadBalancerDescriptor(defintedLoadBalancerCreator.Type, Localizer["CustomLoadBalancer", defintedLoadBalancerCreator.Type]));
}
return loadBalancers;
}
}
}

16
vueJs/src/api/apigateway.ts

@ -164,6 +164,17 @@ export default class ApiGateWay {
_url += '&ReRouteKey=' + routeKey
return ApiService.Delete(_url, serviceUrl)
}
public static getDefinedAggregatorProviders() {
const _url = '/api/ApiGateway/Basic/Aggregators'
return ApiService.Get<ListResultDto<string>>(_url, serviceUrl)
}
public static getLoadBalancerProviders() {
const _url = '/api/ApiGateway/Basic/LoadBalancers'
return ApiService.Get<ListResultDto<LoadBalancerDescriptor>>(_url, serviceUrl)
}
}
export class ServiceDiscoveryProvider {
@ -559,3 +570,8 @@ export class AggregateReRouteGetByPaged extends PagedAndSortedResultRequestDto {
return new AggregateReRouteGetByPaged()
}
}
export class LoadBalancerDescriptor {
type!: string
displayName!: string
}

3
vueJs/src/lang/en.ts

@ -420,7 +420,8 @@ export default {
createAggregateRouteConfig: '新建路由配置',
aggregateRouteKey: '路由标识',
aggregateParameter: '聚合参数',
aggregateJsonPath: 'Json路径'
aggregateJsonPath: 'Json路径',
definedAggregatorProviders: '聚合提供者'
},
identityServer: {
otherOpera: '更多操作',

3
vueJs/src/lang/zh.ts

@ -424,7 +424,8 @@ export default {
createAggregateRouteConfig: '新建路由配置',
aggregateRouteKey: '路由标识',
aggregateParameter: '聚合参数',
aggregateJsonPath: 'Json路径'
aggregateJsonPath: 'Json路径',
definedAggregatorProviders: '聚合提供者'
},
identityServer: {
otherOpera: '更多操作',

37
vueJs/src/views/admin/apigateway/components/AggregateRouteCreateOrEditForm.vue

@ -27,16 +27,34 @@
</el-form-item>
</el-col>
</el-row>
<el-form-item
prop="name"
:label="$t('apiGateWay.aggregateRouteName')"
>
<el-input
v-model="aggregateRoute.name"
:placeholder="$t('pleaseInputBy', {key: $t('apiGateWay.aggregateRouteName')})"
/>
</el-form-item>
<el-row>
<el-col :span="12">
<el-form-item
prop="name"
:label="$t('apiGateWay.aggregateRouteName')"
prop="aggregator"
:label="$t('apiGateWay.definedAggregatorProviders')"
>
<el-input
v-model="aggregateRoute.name"
:placeholder="$t('pleaseInputBy', {key: $t('apiGateWay.aggregateRouteName')})"
/>
<el-select
v-model="aggregateRoute.aggregator"
clearable
style="width: 100%"
:placeholder="$t('pleaseSelectBy', {name: $t('apiGateWay.definedAggregatorProviders')})"
>
<el-option
v-for="(provider, index) in definedAggregatorProviders"
:key="index"
:label="provider"
:value="provider"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
@ -139,6 +157,7 @@ export default class extends Vue {
private appIdOptions!: RouteGroupAppIdDto[]
private aggregateRoute: AggregateReRoute
private definedAggregatorProviders = new Array<string>()
get isEditRoute() {
if (this.aggregateRouteId) {
@ -175,6 +194,12 @@ export default class extends Vue {
this.aggregateRoute = AggregateReRoute.empty()
}
mounted() {
ApiGatewayService.getDefinedAggregatorProviders().then(res => {
this.definedAggregatorProviders = res.items
})
}
@Watch('aggregateRouteId', { immediate: true })
private onAggregateRouteIdChanged() {
if (this.aggregateRouteId) {

21
vueJs/src/views/admin/apigateway/components/GlobalCreateOrEditForm.vue

@ -211,20 +211,15 @@
>
<el-select
v-model="globalConfiguration.loadBalancerOptions.type"
clearable
class="global-select"
:placeholder="$t('pleaseSelectBy', {key: $t('apiGateWay.loadBalancerType')})"
>
<el-option
:label="$t('apiGateWay.leastConnection')"
value="LeastConnection"
/>
<el-option
:label="$t('apiGateWay.roundRobin')"
value="RoundRobin"
/>
<el-option
:label="$t('apiGateWay.noLoadBalance')"
value="NoLoadBalance"
v-for="provider in loadBalancerProviders"
:key="provider.type"
:label="provider.displayName"
:value="provider.type"
/>
</el-select>
</el-form-item>
@ -360,6 +355,7 @@ import { checkPermission } from '@/utils/permission'
import { Component, Vue, Prop, Watch } from 'vue-property-decorator'
import ApiGatewayService, {
RouteGroupAppIdDto,
LoadBalancerDescriptor,
GlobalConfigurationDto,
GlobalConfigurationCreateDto,
GlobalConfigurationUpdateDto
@ -378,11 +374,13 @@ export default class extends Vue {
private globalConfiguration: GlobalConfigurationDto
private routeGroupAppIdOptions: RouteGroupAppIdDto[]
private loadBalancerProviders: LoadBalancerDescriptor[]
constructor() {
super()
this.globalConfiguration = new GlobalConfigurationDto()
this.routeGroupAppIdOptions = new Array<RouteGroupAppIdDto>()
this.loadBalancerProviders = new Array<LoadBalancerDescriptor>()
}
get hasEdit() {
@ -405,6 +403,9 @@ export default class extends Vue {
ApiGatewayService.getRouteGroupAppIds().then(appKeys => {
this.routeGroupAppIdOptions = appKeys.items
})
ApiGatewayService.getLoadBalancerProviders().then(res => {
this.loadBalancerProviders = res.items
})
}
@Watch('appId', { immediate: true })

25
vueJs/src/views/admin/apigateway/components/RouteCreateOrEditForm.vue

@ -392,20 +392,15 @@
>
<el-select
v-model="apiGateWayRoute.loadBalancerOptions.type"
clearable
class="route-select"
:placeholder="$t('pleaseSelectBy', {key: $t('apiGateWay.loadBalancerType')})"
>
<el-option
:label="$t('apiGateWay.leastConnection')"
value="LeastConnection"
/>
<el-option
:label="$t('apiGateWay.roundRobin')"
value="RoundRobin"
/>
<el-option
:label="$t('apiGateWay.noLoadBalance')"
value="NoLoadBalance"
v-for="provider in loadBalancerProviders"
:key="provider.type"
:label="provider.displayName"
:value="provider.type"
/>
</el-select>
</el-form-item>
@ -545,7 +540,7 @@ import ElInputTag from '@/components/InputTag/index.vue'
import HostAndPortInputTag from './HostAndPortInputTag.vue'
import DictionaryInputTag from './DictionaryInputTag.vue'
import { Component, Vue, Prop, Watch } from 'vue-property-decorator'
import ApiGateWayService, { RouteGroupAppIdDto, ReRouteDto, ReRouteCreateDto, ReRouteUpdateDto } from '@/api/apigateway'
import ApiGateWayService, { LoadBalancerDescriptor, RouteGroupAppIdDto, ReRouteDto, ReRouteCreateDto, ReRouteUpdateDto } from '@/api/apigateway'
@Component({
name: 'RouteCreateOrEditForm',
@ -564,6 +559,7 @@ export default class extends Vue {
private activeTablePane: string
private apiGateWayRoute: ReRouteDto
private loadBalancerProviders: LoadBalancerDescriptor[]
private httpMethodsFilter: { [key: string]: string } = {
GET: '',
POST: 'success',
@ -622,6 +618,13 @@ export default class extends Vue {
super()
this.activeTablePane = 'basicOptions'
this.apiGateWayRoute = new ReRouteDto()
this.loadBalancerProviders = new Array<LoadBalancerDescriptor>()
}
mounted() {
ApiGateWayService.getLoadBalancerProviders().then(res => {
this.loadBalancerProviders = res.items
})
}
@Watch('routeId', { immediate: true })

Loading…
Cancel
Save