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 System.Collections.Concurrent;
|
||||
using YarpGateway.Data;
|
||||
using YarpGateway.Models;
|
||||
using Fengling.Platform.Domain.AggregatesModel.GatewayAggregate;
|
||||
|
||||
namespace YarpGateway.Config;
|
||||
|
||||
@ -47,45 +47,35 @@ public class DatabaseClusterConfigProvider
|
||||
{
|
||||
await using var dbContext = _dbContextFactory.CreateDbContext();
|
||||
|
||||
var instances = await dbContext.ServiceInstances
|
||||
.Where(i => i.Status == 1 && !i.IsDeleted)
|
||||
.GroupBy(i => i.ClusterId)
|
||||
var clusters = await dbContext.GwClusters
|
||||
.Where(c => c.Status == 1 && !c.IsDeleted)
|
||||
.Include(c => c.Destinations)
|
||||
.ToListAsync();
|
||||
|
||||
var newClusters = new ConcurrentDictionary<string, ClusterConfig>();
|
||||
|
||||
foreach (var group in instances)
|
||||
foreach (var cluster in clusters)
|
||||
{
|
||||
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>
|
||||
{
|
||||
["Weight"] = instance.Weight.ToString()
|
||||
["Weight"] = dest.Weight.ToString()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var config = new ClusterConfig
|
||||
{
|
||||
ClusterId = group.Key,
|
||||
ClusterId = cluster.ClusterId,
|
||||
Destinations = destinations,
|
||||
LoadBalancingPolicy = "DistributedWeightedRoundRobin",
|
||||
HealthCheck = new HealthCheckConfig
|
||||
{
|
||||
Active = new ActiveHealthCheckConfig
|
||||
{
|
||||
Enabled = true,
|
||||
Interval = TimeSpan.FromSeconds(30),
|
||||
Timeout = TimeSpan.FromSeconds(5),
|
||||
Path = "/health"
|
||||
}
|
||||
}
|
||||
LoadBalancingPolicy = cluster.LoadBalancingPolicy.ToString(),
|
||||
};
|
||||
newClusters[group.Key] = config;
|
||||
newClusters[cluster.ClusterId] = config;
|
||||
}
|
||||
|
||||
_clusters.Clear();
|
||||
|
||||
@ -2,7 +2,7 @@ using System.Collections.Concurrent;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Yarp.ReverseProxy.Configuration;
|
||||
using YarpGateway.Data;
|
||||
using YarpGateway.Models;
|
||||
using Fengling.Platform.Domain.AggregatesModel.GatewayAggregate;
|
||||
|
||||
namespace YarpGateway.Config;
|
||||
|
||||
@ -51,7 +51,7 @@ public class DatabaseRouteConfigProvider
|
||||
await using var dbContext = _dbContextFactory.CreateDbContext();
|
||||
|
||||
var routes = await dbContext
|
||||
.TenantRoutes.Where(r => r.Status == 1 && !r.IsDeleted)
|
||||
.GwTenantRoutes.Where(r => r.Status == 1 && !r.IsDeleted)
|
||||
.ToListAsync();
|
||||
|
||||
var newRoutes = new ConcurrentDictionary<string, RouteConfig>();
|
||||
@ -62,7 +62,7 @@ public class DatabaseRouteConfigProvider
|
||||
{
|
||||
RouteId = route.Id.ToString(),
|
||||
ClusterId = route.ClusterId,
|
||||
Match = new RouteMatch { Path = route.PathPattern },
|
||||
Match = new RouteMatch { Path = route.Match?.Path ?? string.Empty },
|
||||
Metadata = new Dictionary<string, string>
|
||||
{
|
||||
["TenantCode"] = route.TenantCode,
|
||||
|
||||
@ -3,7 +3,8 @@ using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using YarpGateway.Data;
|
||||
using YarpGateway.Config;
|
||||
using YarpGateway.Models;
|
||||
using Fengling.Platform.Domain.AggregatesModel.GatewayAggregate;
|
||||
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
|
||||
using YarpGateway.Services;
|
||||
|
||||
namespace YarpGateway.Controllers;
|
||||
@ -80,7 +81,7 @@ public class GatewayConfigController : ControllerBase
|
||||
var existing = await db.Tenants.FirstOrDefaultAsync(t => t.TenantCode == dto.TenantCode);
|
||||
if (existing != null) return BadRequest($"Tenant code {dto.TenantCode} already exists");
|
||||
|
||||
var tenant = new GwTenant
|
||||
var tenant = new Tenant
|
||||
{
|
||||
Id = GenerateId(),
|
||||
TenantCode = dto.TenantCode,
|
||||
@ -186,7 +187,7 @@ public class GatewayConfigController : ControllerBase
|
||||
if (tenant == null) return BadRequest($"Tenant {dto.TenantCode} not found");
|
||||
}
|
||||
|
||||
var route = new GwTenantRoute
|
||||
var route = new TenantRoute
|
||||
{
|
||||
Id = GenerateId(),
|
||||
TenantCode = dto.TenantCode ?? string.Empty,
|
||||
@ -2,21 +2,22 @@ using Fengling.Platform.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Npgsql;
|
||||
using YarpGateway.Config;
|
||||
using YarpGateway.Models;
|
||||
using Fengling.Platform.Domain.AggregatesModel.GatewayAggregate;
|
||||
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
|
||||
|
||||
namespace YarpGateway.Data;
|
||||
|
||||
public class GatewayDbContext : PlatformDbContext
|
||||
{
|
||||
// DbSet 别名,兼容旧代码
|
||||
public DbSet<GwTenantRoute> TenantRoutes => GwTenantRoutes;
|
||||
public DbSet<GwCluster> ServiceInstances => GwClusters;
|
||||
|
||||
public GatewayDbContext(DbContextOptions<GatewayDbContext> 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)
|
||||
{
|
||||
DetectConfigChanges();
|
||||
@ -45,7 +46,7 @@ public class GatewayDbContext : PlatformDbContext
|
||||
{
|
||||
var entries = ChangeTracker.Entries()
|
||||
.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();
|
||||
}
|
||||
@ -87,40 +88,4 @@ public class GatewayDbContext : PlatformDbContext
|
||||
await using var cmd = new NpgsqlCommand($"NOTIFY {ConfigNotifyChannel.GatewayConfigChanged}", connection);
|
||||
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 db = scope.ServiceProvider.GetRequiredService<GatewayDbContext>();
|
||||
|
||||
var currentRouteVersion = await db.TenantRoutes
|
||||
var currentRouteVersion = await db.GwTenantRoutes
|
||||
.OrderByDescending(r => r.Version)
|
||||
.Select(r => r.Version)
|
||||
.FirstOrDefaultAsync(stoppingToken);
|
||||
|
||||
var currentClusterVersion = await db.ServiceInstances
|
||||
var currentClusterVersion = await db.GwClusters
|
||||
.OrderByDescending(i => i.Version)
|
||||
.Select(i => i.Version)
|
||||
.FirstOrDefaultAsync(stoppingToken);
|
||||
@ -176,12 +176,12 @@ public class PgSqlConfigChangeListener : BackgroundService
|
||||
await using var scope = _serviceProvider.CreateAsyncScope();
|
||||
await using var db = scope.ServiceProvider.GetRequiredService<GatewayDbContext>();
|
||||
|
||||
_lastRouteVersion = await db.TenantRoutes
|
||||
_lastRouteVersion = await db.GwTenantRoutes
|
||||
.OrderByDescending(r => r.Version)
|
||||
.Select(r => r.Version)
|
||||
.FirstOrDefaultAsync(stoppingToken);
|
||||
|
||||
_lastClusterVersion = await db.ServiceInstances
|
||||
_lastClusterVersion = await db.GwClusters
|
||||
.OrderByDescending(i => i.Version)
|
||||
.Select(i => i.Version)
|
||||
.FirstOrDefaultAsync(stoppingToken);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
using System.Collections.Concurrent;
|
||||
using YarpGateway.Models;
|
||||
using Fengling.Platform.Domain.AggregatesModel.GatewayAggregate;
|
||||
using YarpGateway.Data;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@ -8,7 +8,7 @@ namespace YarpGateway.Services;
|
||||
|
||||
public class RouteInfo
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public string Id { get; set; } = string.Empty;
|
||||
public string ClusterId { get; set; } = string.Empty;
|
||||
public string PathPattern { get; set; } = string.Empty;
|
||||
public int Priority { get; set; }
|
||||
@ -95,7 +95,7 @@ public class RouteCache : IRouteCache
|
||||
{
|
||||
using var db = _dbContextFactory.CreateDbContext();
|
||||
|
||||
var routes = await db.TenantRoutes
|
||||
var routes = await db.GwTenantRoutes
|
||||
.Where(r => r.Status == 1 && !r.IsDeleted)
|
||||
.ToListAsync();
|
||||
|
||||
@ -108,11 +108,13 @@ public class RouteCache : IRouteCache
|
||||
|
||||
foreach (var route in routes)
|
||||
{
|
||||
var pathPattern = route.Match?.Path ?? string.Empty;
|
||||
|
||||
var routeInfo = new RouteInfo
|
||||
{
|
||||
Id = route.Id,
|
||||
ClusterId = route.ClusterId,
|
||||
PathPattern = route.PathPattern,
|
||||
PathPattern = pathPattern,
|
||||
Priority = route.Priority,
|
||||
IsGlobal = route.IsGlobal
|
||||
};
|
||||
@ -120,13 +122,13 @@ public class RouteCache : IRouteCache
|
||||
if (route.IsGlobal)
|
||||
{
|
||||
_globalRoutes[route.ServiceName] = routeInfo;
|
||||
_pathRoutes[route.PathPattern] = routeInfo;
|
||||
_pathRoutes[pathPattern] = routeInfo;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(route.TenantCode))
|
||||
{
|
||||
_tenantRoutes.GetOrAdd(route.TenantCode, _ => new())
|
||||
[route.ServiceName] = routeInfo;
|
||||
_pathRoutes[route.PathPattern] = routeInfo;
|
||||
_pathRoutes[pathPattern] = routeInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user