using Nacos.V2.Naming.Dtos; namespace Ocelot.Provider.Nacos.NacosClient; public class WeightRandomLBStrategy : ILBStrategy { public LBStrategyName Name => LBStrategyName.WeightRandom; public Instance GetHost(List list) { var dict = BuildScore(list); Instance instance = null; var rd = new Random().NextDouble(); foreach (var item in dict) { if (item.Value >= rd) { instance = list.FirstOrDefault(x => x.InstanceId.Equals(item.Key)); if (instance == null) { var arr = item.Key.Split("#"); var ip = arr[0]; int.TryParse(arr[1], out var port); var cluster = arr[2]; instance = list.First(x => x.Ip.Equals(ip) && x.Port == port && x.ClusterName.Equals(cluster)); } break; } } return instance; } private Dictionary BuildScore(List list) { var dict = new Dictionary(); // aliyun sae, the instanceid returns empty string // when the instanceid is empty, create a new one, but the group was missed. list.ForEach(x => { x.InstanceId = string.IsNullOrWhiteSpace(x.InstanceId) ? $"{x.Ip}#{x.Port}#{x.ClusterName}#{x.ServiceName}" : x.InstanceId; }); var tmp = list.Select(x => new LbKv { InstanceId = x.InstanceId, Weight = x.Weight }).GroupBy(x => x.InstanceId).Select(x => new LbKv { InstanceId = x.Key, Weight = x.Max(y => y.Weight) }).ToList(); var total = tmp.Sum(x => x.Weight); var cur = 0d; foreach (var item in tmp) { cur += item.Weight; dict.TryAdd(item.InstanceId, cur / total); } return dict; } }