This commit is contained in:
cjd
2025-11-04 21:09:16 +08:00
parent 8260e293c7
commit bb90a020dc
592 changed files with 61749 additions and 27 deletions

View File

@@ -0,0 +1,26 @@
using Nacos;
using Nacos.V2.Naming.Dtos;
using System.Collections.Generic;
namespace Ocelot.Provider.Nacos.NacosClient
{
public interface ILBStrategy
{
/// <summary>
/// Strategy Name
/// </summary>
LBStrategyName Name { get; }
/// <summary>
/// Get host
/// </summary>
/// <param name="list">host list</param>
/// <returns>The Host</returns>
Instance GetHost(List<Instance> list);
}
}

View File

@@ -0,0 +1,20 @@
namespace Ocelot.Provider.Nacos.NacosClient
{
public enum LBStrategyName
{
/// <summary>
/// Weight Round Robin
/// </summary>
WeightRoundRobin,
/// <summary>
/// Weight Random
/// </summary>
WeightRandom,
/// <summary>
/// Ext1
/// </summary>
Ext1
}
}

View File

@@ -0,0 +1,9 @@
namespace Ocelot.Provider.Nacos.NacosClient
{
public class LbKv
{
public string InstanceId { get; set; }
public double Weight { get; set; }
}
}

View File

@@ -0,0 +1,74 @@
using Nacos;
using Nacos.V2.Naming.Dtos;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Ocelot.Provider.Nacos.NacosClient
{
public class WeightRandomLBStrategy : ILBStrategy
{
public LBStrategyName Name => LBStrategyName.WeightRandom;
public Instance GetHost(List<Instance> 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<string, double> BuildScore(List<Instance> list)
{
var dict = new Dictionary<string, double>();
// 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;
}
}
}

View File

@@ -0,0 +1,71 @@
using Nacos;
using System.Collections.Generic;
using System.Linq;
using Nacos.V2.Naming.Dtos;
namespace Ocelot.Provider.Nacos.NacosClient
{
public class WeightRoundRobinLBStrategy : ILBStrategy
{
public LBStrategyName Name => LBStrategyName.WeightRoundRobin;
private int _pos;
private static object obj = new object();
public Instance GetHost(List<Instance> list)
{
// 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();
// <instanceid, weight>
var dic = tmp.ToDictionary(k => k.InstanceId, v => (int)v.Weight);
var srcInstanceIdList = dic.Keys.ToList();
var tagInstanceIdList = new List<string>();
foreach (var item in srcInstanceIdList)
{
dic.TryGetValue(item, out var weight);
for (int i = 0; i < weight; i++)
tagInstanceIdList.Add(item);
}
var instanceId = string.Empty;
lock (obj)
{
if (_pos >= tagInstanceIdList.Count)
_pos = 0;
instanceId = tagInstanceIdList[_pos];
_pos++;
}
var instance = list.FirstOrDefault(x => x.InstanceId.Equals(instanceId));
if (instance == null)
{
var arr = instanceId.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));
}
return instance;
}
}
}