init
This commit is contained in:
26
Ocelot.Provider.Nacos/NacosClient/LoadBalance/ILBStrategy.cs
Normal file
26
Ocelot.Provider.Nacos/NacosClient/LoadBalance/ILBStrategy.cs
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
9
Ocelot.Provider.Nacos/NacosClient/LoadBalance/LbKv.cs
Normal file
9
Ocelot.Provider.Nacos/NacosClient/LoadBalance/LbKv.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace Ocelot.Provider.Nacos.NacosClient
|
||||
{
|
||||
public class LbKv
|
||||
{
|
||||
public string InstanceId { get; set; }
|
||||
|
||||
public double Weight { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user