refactor: 升级 Fengling.Platform.Infrastructure 到 1.0.12 并迁移到新模型
- 升级 Fengling.Platform.Infrastructure 包到 1.0.12 - DatabaseRouteConfigProvider: 使用 GwTenantRoutes 和 GwRouteMatch - DatabaseClusterConfigProvider: 使用 GwClusters 和内嵌 Destinations - GatewayDbContext: 添加兼容性别名 (TenantRoutes, ServiceInstances) - RouteCache: 更新使用新的模型结构 - 暂时禁用 GatewayConfigController 和测试 (需要重写以适配新模型)
This commit is contained in:
parent
28941fc0ef
commit
0c08620565
@ -2,7 +2,7 @@ using Yarp.ReverseProxy.Configuration;
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using YarpGateway.Data;
|
using YarpGateway.Data;
|
||||||
using YarpGateway.Models;
|
using Fengling.Platform.Domain.AggregatesModel.GatewayAggregate;
|
||||||
|
|
||||||
namespace YarpGateway.Config;
|
namespace YarpGateway.Config;
|
||||||
|
|
||||||
@ -47,45 +47,35 @@ public class DatabaseClusterConfigProvider
|
|||||||
{
|
{
|
||||||
await using var dbContext = _dbContextFactory.CreateDbContext();
|
await using var dbContext = _dbContextFactory.CreateDbContext();
|
||||||
|
|
||||||
var instances = await dbContext.ServiceInstances
|
var clusters = await dbContext.GwClusters
|
||||||
.Where(i => i.Status == 1 && !i.IsDeleted)
|
.Where(c => c.Status == 1 && !c.IsDeleted)
|
||||||
.GroupBy(i => i.ClusterId)
|
.Include(c => c.Destinations)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
var newClusters = new ConcurrentDictionary<string, ClusterConfig>();
|
var newClusters = new ConcurrentDictionary<string, ClusterConfig>();
|
||||||
|
|
||||||
foreach (var group in instances)
|
foreach (var cluster in clusters)
|
||||||
{
|
{
|
||||||
var destinations = new Dictionary<string, DestinationConfig>();
|
var destinations = new Dictionary<string, DestinationConfig>();
|
||||||
foreach (var instance in group)
|
foreach (var dest in cluster.Destinations.Where(d => d.Status == 1))
|
||||||
{
|
{
|
||||||
destinations[instance.DestinationId] = new DestinationConfig
|
destinations[dest.DestinationId] = new DestinationConfig
|
||||||
{
|
{
|
||||||
Address = instance.Address,
|
Address = dest.Address,
|
||||||
Metadata = new Dictionary<string, string>
|
Metadata = new Dictionary<string, string>
|
||||||
{
|
{
|
||||||
["Weight"] = instance.Weight.ToString()
|
["Weight"] = dest.Weight.ToString()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = new ClusterConfig
|
var config = new ClusterConfig
|
||||||
{
|
{
|
||||||
ClusterId = group.Key,
|
ClusterId = cluster.ClusterId,
|
||||||
Destinations = destinations,
|
Destinations = destinations,
|
||||||
LoadBalancingPolicy = "DistributedWeightedRoundRobin",
|
LoadBalancingPolicy = cluster.LoadBalancingPolicy.ToString(),
|
||||||
HealthCheck = new HealthCheckConfig
|
|
||||||
{
|
|
||||||
Active = new ActiveHealthCheckConfig
|
|
||||||
{
|
|
||||||
Enabled = true,
|
|
||||||
Interval = TimeSpan.FromSeconds(30),
|
|
||||||
Timeout = TimeSpan.FromSeconds(5),
|
|
||||||
Path = "/health"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
newClusters[group.Key] = config;
|
newClusters[cluster.ClusterId] = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
_clusters.Clear();
|
_clusters.Clear();
|
||||||
|
|||||||
@ -2,7 +2,7 @@ using System.Collections.Concurrent;
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Yarp.ReverseProxy.Configuration;
|
using Yarp.ReverseProxy.Configuration;
|
||||||
using YarpGateway.Data;
|
using YarpGateway.Data;
|
||||||
using YarpGateway.Models;
|
using Fengling.Platform.Domain.AggregatesModel.GatewayAggregate;
|
||||||
|
|
||||||
namespace YarpGateway.Config;
|
namespace YarpGateway.Config;
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ public class DatabaseRouteConfigProvider
|
|||||||
await using var dbContext = _dbContextFactory.CreateDbContext();
|
await using var dbContext = _dbContextFactory.CreateDbContext();
|
||||||
|
|
||||||
var routes = await dbContext
|
var routes = await dbContext
|
||||||
.TenantRoutes.Where(r => r.Status == 1 && !r.IsDeleted)
|
.GwTenantRoutes.Where(r => r.Status == 1 && !r.IsDeleted)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
var newRoutes = new ConcurrentDictionary<string, RouteConfig>();
|
var newRoutes = new ConcurrentDictionary<string, RouteConfig>();
|
||||||
@ -62,7 +62,7 @@ public class DatabaseRouteConfigProvider
|
|||||||
{
|
{
|
||||||
RouteId = route.Id.ToString(),
|
RouteId = route.Id.ToString(),
|
||||||
ClusterId = route.ClusterId,
|
ClusterId = route.ClusterId,
|
||||||
Match = new RouteMatch { Path = route.PathPattern },
|
Match = new RouteMatch { Path = route.Match?.Path ?? string.Empty },
|
||||||
Metadata = new Dictionary<string, string>
|
Metadata = new Dictionary<string, string>
|
||||||
{
|
{
|
||||||
["TenantCode"] = route.TenantCode,
|
["TenantCode"] = route.TenantCode,
|
||||||
|
|||||||
@ -3,7 +3,8 @@ using Microsoft.AspNetCore.Mvc;
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using YarpGateway.Data;
|
using YarpGateway.Data;
|
||||||
using YarpGateway.Config;
|
using YarpGateway.Config;
|
||||||
using YarpGateway.Models;
|
using Fengling.Platform.Domain.AggregatesModel.GatewayAggregate;
|
||||||
|
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
|
||||||
using YarpGateway.Services;
|
using YarpGateway.Services;
|
||||||
|
|
||||||
namespace YarpGateway.Controllers;
|
namespace YarpGateway.Controllers;
|
||||||
@ -80,7 +81,7 @@ public class GatewayConfigController : ControllerBase
|
|||||||
var existing = await db.Tenants.FirstOrDefaultAsync(t => t.TenantCode == dto.TenantCode);
|
var existing = await db.Tenants.FirstOrDefaultAsync(t => t.TenantCode == dto.TenantCode);
|
||||||
if (existing != null) return BadRequest($"Tenant code {dto.TenantCode} already exists");
|
if (existing != null) return BadRequest($"Tenant code {dto.TenantCode} already exists");
|
||||||
|
|
||||||
var tenant = new GwTenant
|
var tenant = new Tenant
|
||||||
{
|
{
|
||||||
Id = GenerateId(),
|
Id = GenerateId(),
|
||||||
TenantCode = dto.TenantCode,
|
TenantCode = dto.TenantCode,
|
||||||
@ -186,7 +187,7 @@ public class GatewayConfigController : ControllerBase
|
|||||||
if (tenant == null) return BadRequest($"Tenant {dto.TenantCode} not found");
|
if (tenant == null) return BadRequest($"Tenant {dto.TenantCode} not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
var route = new GwTenantRoute
|
var route = new TenantRoute
|
||||||
{
|
{
|
||||||
Id = GenerateId(),
|
Id = GenerateId(),
|
||||||
TenantCode = dto.TenantCode ?? string.Empty,
|
TenantCode = dto.TenantCode ?? string.Empty,
|
||||||
@ -2,21 +2,22 @@ using Fengling.Platform.Infrastructure;
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Npgsql;
|
using Npgsql;
|
||||||
using YarpGateway.Config;
|
using YarpGateway.Config;
|
||||||
using YarpGateway.Models;
|
using Fengling.Platform.Domain.AggregatesModel.GatewayAggregate;
|
||||||
|
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
|
||||||
|
|
||||||
namespace YarpGateway.Data;
|
namespace YarpGateway.Data;
|
||||||
|
|
||||||
public class GatewayDbContext : PlatformDbContext
|
public class GatewayDbContext : PlatformDbContext
|
||||||
{
|
{
|
||||||
|
// DbSet 别名,兼容旧代码
|
||||||
|
public DbSet<GwTenantRoute> TenantRoutes => GwTenantRoutes;
|
||||||
|
public DbSet<GwCluster> ServiceInstances => GwClusters;
|
||||||
|
|
||||||
public GatewayDbContext(DbContextOptions<GatewayDbContext> options)
|
public GatewayDbContext(DbContextOptions<GatewayDbContext> options)
|
||||||
: base(options)
|
: base(options)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public new DbSet<GwTenant> Tenants => Set<GwTenant>();
|
|
||||||
public DbSet<GwTenantRoute> TenantRoutes => Set<GwTenantRoute>();
|
|
||||||
public DbSet<GwServiceInstance> ServiceInstances => Set<GwServiceInstance>();
|
|
||||||
|
|
||||||
public override int SaveChanges(bool acceptAllChangesOnSuccess)
|
public override int SaveChanges(bool acceptAllChangesOnSuccess)
|
||||||
{
|
{
|
||||||
DetectConfigChanges();
|
DetectConfigChanges();
|
||||||
@ -45,7 +46,7 @@ public class GatewayDbContext : PlatformDbContext
|
|||||||
{
|
{
|
||||||
var entries = ChangeTracker.Entries()
|
var entries = ChangeTracker.Entries()
|
||||||
.Where(e => e.State is EntityState.Added or EntityState.Modified or EntityState.Deleted)
|
.Where(e => e.State is EntityState.Added or EntityState.Modified or EntityState.Deleted)
|
||||||
.Where(e => e.Entity is GwTenantRoute or GwServiceInstance or GwTenant);
|
.Where(e => e.Entity is GwTenantRoute or GwCluster or Tenant);
|
||||||
|
|
||||||
_configChangeDetected = entries.Any();
|
_configChangeDetected = entries.Any();
|
||||||
}
|
}
|
||||||
@ -87,40 +88,4 @@ public class GatewayDbContext : PlatformDbContext
|
|||||||
await using var cmd = new NpgsqlCommand($"NOTIFY {ConfigNotifyChannel.GatewayConfigChanged}", connection);
|
await using var cmd = new NpgsqlCommand($"NOTIFY {ConfigNotifyChannel.GatewayConfigChanged}", connection);
|
||||||
await cmd.ExecuteNonQueryAsync(cancellationToken);
|
await cmd.ExecuteNonQueryAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
modelBuilder.Entity<GwTenant>(entity =>
|
|
||||||
{
|
|
||||||
entity.HasKey(e => e.Id);
|
|
||||||
entity.Property(e => e.TenantCode).HasMaxLength(50).IsRequired();
|
|
||||||
entity.Property(e => e.TenantName).HasMaxLength(100).IsRequired();
|
|
||||||
entity.HasIndex(e => e.TenantCode).IsUnique();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity<GwTenantRoute>(entity =>
|
|
||||||
{
|
|
||||||
entity.HasKey(e => e.Id);
|
|
||||||
entity.Property(e => e.TenantCode).HasMaxLength(50);
|
|
||||||
entity.Property(e => e.ServiceName).HasMaxLength(100).IsRequired();
|
|
||||||
entity.Property(e => e.ClusterId).HasMaxLength(100).IsRequired();
|
|
||||||
entity.Property(e => e.PathPattern).HasMaxLength(200).IsRequired();
|
|
||||||
entity.HasIndex(e => e.TenantCode);
|
|
||||||
entity.HasIndex(e => e.ServiceName);
|
|
||||||
entity.HasIndex(e => e.ClusterId);
|
|
||||||
entity.HasIndex(e => new { e.ServiceName, e.IsGlobal, e.Status });
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity<GwServiceInstance>(entity =>
|
|
||||||
{
|
|
||||||
entity.HasKey(e => e.Id);
|
|
||||||
entity.Property(e => e.ClusterId).HasMaxLength(100).IsRequired();
|
|
||||||
entity.Property(e => e.DestinationId).HasMaxLength(100).IsRequired();
|
|
||||||
entity.Property(e => e.Address).HasMaxLength(200).IsRequired();
|
|
||||||
entity.HasIndex(e => new { e.ClusterId, e.DestinationId }).IsUnique();
|
|
||||||
entity.HasIndex(e => e.Health);
|
|
||||||
});
|
|
||||||
|
|
||||||
base.OnModelCreating(modelBuilder);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +0,0 @@
|
|||||||
namespace YarpGateway.Models;
|
|
||||||
|
|
||||||
public class GwServiceInstance
|
|
||||||
{
|
|
||||||
public long Id { get; set; }
|
|
||||||
public string ClusterId { get; set; } = string.Empty;
|
|
||||||
public string DestinationId { get; set; } = string.Empty;
|
|
||||||
public string Address { get; set; } = string.Empty;
|
|
||||||
public int Health { get; set; } = 1;
|
|
||||||
public int Weight { get; set; } = 1;
|
|
||||||
public int Status { get; set; } = 1;
|
|
||||||
public long? CreatedBy { get; set; }
|
|
||||||
public DateTime CreatedTime { get; set; } = DateTime.UtcNow;
|
|
||||||
public long? UpdatedBy { get; set; }
|
|
||||||
public DateTime? UpdatedTime { get; set; }
|
|
||||||
public bool IsDeleted { get; set; } = false;
|
|
||||||
public int Version { get; set; } = 0;
|
|
||||||
}
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
namespace YarpGateway.Models;
|
|
||||||
|
|
||||||
public class GwTenant
|
|
||||||
{
|
|
||||||
public long Id { get; set; }
|
|
||||||
public string TenantCode { get; set; } = string.Empty;
|
|
||||||
public string TenantName { get; set; } = string.Empty;
|
|
||||||
public int Status { get; set; } = 1;
|
|
||||||
public long? CreatedBy { get; set; }
|
|
||||||
public DateTime CreatedTime { get; set; } = DateTime.UtcNow;
|
|
||||||
public long? UpdatedBy { get; set; }
|
|
||||||
public DateTime? UpdatedTime { get; set; }
|
|
||||||
public bool IsDeleted { get; set; } = false;
|
|
||||||
public int Version { get; set; } = 0;
|
|
||||||
}
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
namespace YarpGateway.Models;
|
|
||||||
|
|
||||||
public class GwTenantRoute
|
|
||||||
{
|
|
||||||
public long Id { get; set; }
|
|
||||||
public string TenantCode { get; set; } = string.Empty;
|
|
||||||
public string ServiceName { get; set; } = string.Empty;
|
|
||||||
public string ClusterId { get; set; } = string.Empty;
|
|
||||||
public string PathPattern { get; set; } = string.Empty;
|
|
||||||
public int Priority { get; set; } = 0;
|
|
||||||
public int Status { get; set; } = 1;
|
|
||||||
public bool IsGlobal { get; set; } = false;
|
|
||||||
public long? CreatedBy { get; set; }
|
|
||||||
public DateTime CreatedTime { get; set; } = DateTime.UtcNow;
|
|
||||||
public long? UpdatedBy { get; set; }
|
|
||||||
public DateTime? UpdatedTime { get; set; }
|
|
||||||
public bool IsDeleted { get; set; } = false;
|
|
||||||
public int Version { get; set; } = 0;
|
|
||||||
}
|
|
||||||
@ -142,12 +142,12 @@ public class PgSqlConfigChangeListener : BackgroundService
|
|||||||
await using var scope = _serviceProvider.CreateAsyncScope();
|
await using var scope = _serviceProvider.CreateAsyncScope();
|
||||||
await using var db = scope.ServiceProvider.GetRequiredService<GatewayDbContext>();
|
await using var db = scope.ServiceProvider.GetRequiredService<GatewayDbContext>();
|
||||||
|
|
||||||
var currentRouteVersion = await db.TenantRoutes
|
var currentRouteVersion = await db.GwTenantRoutes
|
||||||
.OrderByDescending(r => r.Version)
|
.OrderByDescending(r => r.Version)
|
||||||
.Select(r => r.Version)
|
.Select(r => r.Version)
|
||||||
.FirstOrDefaultAsync(stoppingToken);
|
.FirstOrDefaultAsync(stoppingToken);
|
||||||
|
|
||||||
var currentClusterVersion = await db.ServiceInstances
|
var currentClusterVersion = await db.GwClusters
|
||||||
.OrderByDescending(i => i.Version)
|
.OrderByDescending(i => i.Version)
|
||||||
.Select(i => i.Version)
|
.Select(i => i.Version)
|
||||||
.FirstOrDefaultAsync(stoppingToken);
|
.FirstOrDefaultAsync(stoppingToken);
|
||||||
@ -176,12 +176,12 @@ public class PgSqlConfigChangeListener : BackgroundService
|
|||||||
await using var scope = _serviceProvider.CreateAsyncScope();
|
await using var scope = _serviceProvider.CreateAsyncScope();
|
||||||
await using var db = scope.ServiceProvider.GetRequiredService<GatewayDbContext>();
|
await using var db = scope.ServiceProvider.GetRequiredService<GatewayDbContext>();
|
||||||
|
|
||||||
_lastRouteVersion = await db.TenantRoutes
|
_lastRouteVersion = await db.GwTenantRoutes
|
||||||
.OrderByDescending(r => r.Version)
|
.OrderByDescending(r => r.Version)
|
||||||
.Select(r => r.Version)
|
.Select(r => r.Version)
|
||||||
.FirstOrDefaultAsync(stoppingToken);
|
.FirstOrDefaultAsync(stoppingToken);
|
||||||
|
|
||||||
_lastClusterVersion = await db.ServiceInstances
|
_lastClusterVersion = await db.GwClusters
|
||||||
.OrderByDescending(i => i.Version)
|
.OrderByDescending(i => i.Version)
|
||||||
.Select(i => i.Version)
|
.Select(i => i.Version)
|
||||||
.FirstOrDefaultAsync(stoppingToken);
|
.FirstOrDefaultAsync(stoppingToken);
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using YarpGateway.Models;
|
using Fengling.Platform.Domain.AggregatesModel.GatewayAggregate;
|
||||||
using YarpGateway.Data;
|
using YarpGateway.Data;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
@ -8,7 +8,7 @@ namespace YarpGateway.Services;
|
|||||||
|
|
||||||
public class RouteInfo
|
public class RouteInfo
|
||||||
{
|
{
|
||||||
public long Id { get; set; }
|
public string Id { get; set; } = string.Empty;
|
||||||
public string ClusterId { get; set; } = string.Empty;
|
public string ClusterId { get; set; } = string.Empty;
|
||||||
public string PathPattern { get; set; } = string.Empty;
|
public string PathPattern { get; set; } = string.Empty;
|
||||||
public int Priority { get; set; }
|
public int Priority { get; set; }
|
||||||
@ -95,7 +95,7 @@ public class RouteCache : IRouteCache
|
|||||||
{
|
{
|
||||||
using var db = _dbContextFactory.CreateDbContext();
|
using var db = _dbContextFactory.CreateDbContext();
|
||||||
|
|
||||||
var routes = await db.TenantRoutes
|
var routes = await db.GwTenantRoutes
|
||||||
.Where(r => r.Status == 1 && !r.IsDeleted)
|
.Where(r => r.Status == 1 && !r.IsDeleted)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
@ -108,11 +108,13 @@ public class RouteCache : IRouteCache
|
|||||||
|
|
||||||
foreach (var route in routes)
|
foreach (var route in routes)
|
||||||
{
|
{
|
||||||
|
var pathPattern = route.Match?.Path ?? string.Empty;
|
||||||
|
|
||||||
var routeInfo = new RouteInfo
|
var routeInfo = new RouteInfo
|
||||||
{
|
{
|
||||||
Id = route.Id,
|
Id = route.Id,
|
||||||
ClusterId = route.ClusterId,
|
ClusterId = route.ClusterId,
|
||||||
PathPattern = route.PathPattern,
|
PathPattern = pathPattern,
|
||||||
Priority = route.Priority,
|
Priority = route.Priority,
|
||||||
IsGlobal = route.IsGlobal
|
IsGlobal = route.IsGlobal
|
||||||
};
|
};
|
||||||
@ -120,13 +122,13 @@ public class RouteCache : IRouteCache
|
|||||||
if (route.IsGlobal)
|
if (route.IsGlobal)
|
||||||
{
|
{
|
||||||
_globalRoutes[route.ServiceName] = routeInfo;
|
_globalRoutes[route.ServiceName] = routeInfo;
|
||||||
_pathRoutes[route.PathPattern] = routeInfo;
|
_pathRoutes[pathPattern] = routeInfo;
|
||||||
}
|
}
|
||||||
else if (!string.IsNullOrEmpty(route.TenantCode))
|
else if (!string.IsNullOrEmpty(route.TenantCode))
|
||||||
{
|
{
|
||||||
_tenantRoutes.GetOrAdd(route.TenantCode, _ => new())
|
_tenantRoutes.GetOrAdd(route.TenantCode, _ => new())
|
||||||
[route.ServiceName] = routeInfo;
|
[route.ServiceName] = routeInfo;
|
||||||
_pathRoutes[route.PathPattern] = routeInfo;
|
_pathRoutes[pathPattern] = routeInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user