using Nacos.V2; using Newtonsoft.Json; using System.Threading.Tasks; using Yarp.ReverseProxy.Configuration; namespace YuanXuan.IM.Api.Proxy { /// /// Nacos代理配置提供者 /// public class NacosProxyConfigProvider : IProxyConfigProvider { private readonly INacosNamingService _nacosNamingService; private readonly IConfiguration _configuration; private volatile IProxyConfig _config; private CancellationTokenSource _cts; public NacosProxyConfigProvider(INacosNamingService nacosNamingService, IConfiguration configuration) { _nacosNamingService = nacosNamingService; _configuration = configuration; // 立即从Nacos获取服务实例 _config = CreateConfig(); // 通知YARP配置已变更 ProxyConfig.SignalChange(); _cts = new CancellationTokenSource(); // 启动后台任务,定期从Nacos更新服务实例 Task.Run(async () => await UpdateConfigPeriodically(), _cts.Token); } /// /// 创建配置 /// /// private IProxyConfig CreateConfig() { var routes = new List { new RouteConfig { RouteId = "api_route", ClusterId = "api_cluster", Match = new RouteMatch { Path = "/api/{**catch-all}" } }, new RouteConfig { RouteId = "user_route", ClusterId = "user_cluster", Match = new RouteMatch { Path = "/user/{**catch-all}" } }, new RouteConfig { RouteId = "testdemo1", ClusterId = "test_cluster", Match = new RouteMatch { Path = "/test/{**catch-all}" } } }; var clusters = new List(); try { // 从Nacos获取YuanXuan.Api服务实例,指定分组为qx-im var apiServiceInstances = _nacosNamingService.GetAllInstances("YuanXuan.Api", "qx-im").Result; if (apiServiceInstances.Any()) { // 创建api_cluster集群配置 var apiDestinations = new Dictionary(); foreach (var instance in apiServiceInstances) { if (instance.Healthy) { var destinationId = $"{instance.Ip}:{instance.Port}"; apiDestinations.Add(destinationId, new DestinationConfig { Address = $"http://{instance.Ip}:{instance.Port}" }); } } clusters.Add(new ClusterConfig { ClusterId = "api_cluster", Destinations = apiDestinations }); } // 从Nacos获取User.Service服务实例,指定分组为qx-im try { var userServiceInstances = _nacosNamingService.GetAllInstances("User.Service", "qx-im").Result; if (userServiceInstances.Any()) { // 创建user_cluster集群配置 var userDestinations = new Dictionary(); foreach (var instance in userServiceInstances) { if (instance.Healthy) { var destinationId = $"{instance.Ip}:{instance.Port}"; userDestinations.Add(destinationId, new DestinationConfig { Address = $"http://{instance.Ip}:{instance.Port}" }); } } clusters.Add(new ClusterConfig { ClusterId = "user_cluster", Destinations = userDestinations }); } } catch (Exception ex) { Console.WriteLine($"从Nacos获取User.Service服务实例失败: {ex.Message}"); } // 从Nacos获取Test.Service服务实例,指定分组为qx-im try { var testServiceInstances = _nacosNamingService.GetAllInstances("Test.Service", "qx-im").Result; if (testServiceInstances.Any()) { // 创建test_cluster集群配置 var testDestinations = new Dictionary(); foreach (var instance in testServiceInstances) { if (instance.Healthy) { var destinationId = $"{instance.Ip}:{instance.Port}"; testDestinations.Add(destinationId, new DestinationConfig { Address = $"http://{instance.Ip}:{instance.Port}" }); } } clusters.Add(new ClusterConfig { ClusterId = "test_cluster", Destinations = testDestinations }); } } catch (Exception ex) { Console.WriteLine($"从Nacos获取Test.Service服务实例失败: {ex.Message}"); } Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}:" + JsonConvert.SerializeObject(clusters)); } catch (Exception ex) { Console.WriteLine($"从Nacos获取服务实例失败: {ex.Message}"); } // 如果没有从Nacos获取到api_cluster集群,使用默认配置 if (!clusters.Any(c => c.ClusterId == "api_cluster")) { clusters.Add(new ClusterConfig { ClusterId = "api_cluster", Destinations = new Dictionary { { "default", new DestinationConfig { Address = "http://localhost:5001" } } } }); } // 如果没有从Nacos获取到user_cluster集群,使用默认配置 if (!clusters.Any(c => c.ClusterId == "user_cluster")) { clusters.Add(new ClusterConfig { ClusterId = "user_cluster", Destinations = new Dictionary { { "default", new DestinationConfig { Address = "http://localhost:5181" } } } }); } // 如果没有从Nacos获取到test_cluster集群,使用默认配置 if (!clusters.Any(c => c.ClusterId == "test_cluster")) { clusters.Add(new ClusterConfig { ClusterId = "test_cluster", Destinations = new Dictionary { { "default", new DestinationConfig { Address = "http://localhost:5252" } } } }); } return new ProxyConfig(routes, clusters, DateTime.UtcNow); } /// /// 获取代理配置 /// /// public IProxyConfig GetConfig() => _config; /// /// 定期更新配置 /// /// private async Task UpdateConfigPeriodically() { while (!_cts.Token.IsCancellationRequested) { try { await Task.Delay(TimeSpan.FromSeconds(30), _cts.Token); // 每30秒更新一次 await UpdateConfig(); } catch (TaskCanceledException) { // 任务被取消,退出循环 break; } catch (Exception ex) { Console.WriteLine($"更新Nacos代理配置失败: {ex.Message}"); } } } /// /// 更新配置 /// /// private async Task UpdateConfig() { // 重新从Nacos获取服务实例并更新配置 _config = CreateConfig(); // 通知YARP配置已变更 ProxyConfig.SignalChange(); } } }