private void OnChanged(ZooyardOption value, string name) { Logger().LogInformation($"{name} has changed:{ value}"); Console.WriteLine($"{name} has changed:{ value}"); this.Address = URL.ValueOf(value.RegisterUrl); foreach (var item in value.Clients) { var list = item.Value.Urls.Select(w => URL.ValueOf(w).AddParameterIfAbsent("interface", item.Value.Service.FullName)).ToList(); //优先移除被隔离了的URL if (this.BadUrls.ContainsKey(item.Key)) { var removeUrls = new List <BadUrl>(); foreach (var badUrl in this.BadUrls[item.Key]) { var exitsUrl = list.FirstOrDefault(w => w.ToIdentityString() == badUrl.Url.ToIdentityString()); if (exitsUrl == null) { removeUrls.Add(badUrl); } } foreach (var url in removeUrls) { this.BadUrls[item.Key].Remove(url); } } if (this.Urls.ContainsKey(item.Key)) { //移除注销的提供者 var removeUrls = new List <URL>(); foreach (var url in this.Urls[item.Key]) { var exitsUrl = list.FirstOrDefault(w => w.ToIdentityString() == url.ToIdentityString()); if (exitsUrl == null) { removeUrls.Add(url); } } foreach (var url in removeUrls) { this.Urls[item.Key].Remove(url); } //发现新的提供者 foreach (var i in list) { URL exitsUrl = null; if (this.Urls.TryGetValue(item.Key, out IList <URL> urlList)) { exitsUrl = urlList.FirstOrDefault(w => w.ToIdentityString() == i.ToIdentityString()); } BadUrl exitsBadUrl = null; if (BadUrls.TryGetValue(item.Key, out IList <BadUrl> badUrlList)) { badUrlList.FirstOrDefault(w => w.Url.ToIdentityString() == i.ToIdentityString()); } if (exitsUrl == null && exitsBadUrl == null) { this.Urls[item.Key].Add(i); } } } else { this.Urls.TryAdd(item.Key, list); } } }
public static void AddZoolandClient(this IServiceCollection services, IConfiguration config, string zooyard = "zooyard") { services.AddSingleton <IDictionary <string, IClientPool> >((serviceProvder) => { var option = serviceProvder.GetService <IOptionsMonitor <ZooyardOption> >().CurrentValue; var result = new Dictionary <string, IClientPool>(); foreach (var item in option.Clients) { var pool = serviceProvder.GetService(Type.GetType(item.Value.PoolType)) as IClientPool; result.Add(item.Value.Service.FullName, pool); } return(result); }); services.AddSingleton <ILoadBalance, ConsistentHashLoadBalance>(); services.AddSingleton <ILoadBalance, LeastActiveLoadBalance>(); services.AddSingleton <ILoadBalance, RandomLoadBalance>(); services.AddSingleton <ILoadBalance, RoundRobinLoadBalance>(); services.AddSingleton <ICluster, BroadcastCluster>(); services.AddSingleton <ICluster, FailbackCluster>(); services.AddSingleton <ICluster, FailfastCluster>(); services.AddSingleton <ICluster, FailoverCluster>(); services.AddSingleton <ICluster, FailsafeCluster>(); services.AddSingleton <ICluster, ForkingCluster>(); services.AddSingleton <ArrayMerger>(); services.AddSingleton <BooleanArrayMerger>(); services.AddSingleton <ByteArrayMerger>(); services.AddSingleton <CharArrayMerger>(); services.AddSingleton <DoubleArrayMerger>(); services.AddSingleton <FloatArrayMerger>(); services.AddSingleton <ShortArrayMerger>(); services.AddSingleton <IntArrayMerger>(); services.AddSingleton <LongArrayMerger>(); services.AddSingleton(typeof(ListMerger <>)); services.AddSingleton(typeof(DictionaryMerger <,>)); services.AddSingleton(typeof(SetMerger <>)); services.AddSingleton <IDictionary <Type, IMerger> >((serviceProvder) => { var result = new Dictionary <Type, IMerger> { { typeof(Array), serviceProvder.GetService <ArrayMerger>() }, { typeof(bool), serviceProvder.GetService <BooleanArrayMerger>() }, { typeof(byte), serviceProvder.GetService <ByteArrayMerger>() }, { typeof(char), serviceProvder.GetService <CharArrayMerger>() }, { typeof(double), serviceProvder.GetService <DoubleArrayMerger>() }, { typeof(float), serviceProvder.GetService <FloatArrayMerger>() }, { typeof(short), serviceProvder.GetService <ShortArrayMerger>() }, { typeof(int), serviceProvder.GetService <IntArrayMerger>() }, { typeof(long), serviceProvder.GetService <LongArrayMerger>() }, { typeof(IEnumerable <>), serviceProvder.GetService(typeof(ListMerger <>)) as IMerger }, { typeof(IDictionary <,>), serviceProvder.GetService(typeof(DictionaryMerger <,>)) as IMerger }, { typeof(ISet <>), serviceProvder.GetService(typeof(SetMerger <>)) as IMerger } }; return(result); }); services.AddSingleton <IDictionary <string, IMerger> >((serviceProvder) => { var option = serviceProvder.GetService <IOptionsMonitor <ZooyardOption> >().CurrentValue; var result = new Dictionary <string, IMerger>(); foreach (var item in option.Mergers) { var merger = serviceProvder.GetService(Type.GetType(item.Value)) as IMerger; result.Add(item.Key, merger); } return(result); }); services.AddSingleton <MergeableCluster>(); var caches = new Dictionary <string, Type> { { "local", typeof(LocalCache) }, { "lru", typeof(LruCache) }, { "threadlocal", typeof(ThreadLocalCache) }, }; services.AddSingleton <IZooyardPools>((serviceProvder) => { var option = serviceProvder.GetService <IOptionsMonitor <ZooyardOption> >(); var clientPools = serviceProvder.GetService <IDictionary <string, IClientPool> >(); var loadbalanceList = serviceProvder.GetServices <ILoadBalance>(); var loadBalances = new Dictionary <string, ILoadBalance>(); foreach (var item in loadbalanceList) { loadBalances.Add(item.Name, item); } ; var clusterList = serviceProvder.GetServices <ICluster>(); var clusters = new Dictionary <string, ICluster>(); foreach (var item in clusterList) { clusters.Add(item.Name, item); } var zooyardPools = new ZooyardPools(clientPools, loadBalances, clusters, caches, option); return(zooyardPools); }); var optionData = new ZooyardOption(); config.Bind(zooyard, optionData); foreach (var item in optionData.Clients) { var serviceType = Type.GetType(item.Value.ServiceType); if (serviceType == null) { var msg = $"waring {zooyard} not find type {item.Value.ServiceType}"; Logger().LogWarning(msg); Console.WriteLine(msg); continue; } var genericType = typeof(ZooyardFactory <>); var factoryType = genericType.MakeGenericType(new [] { serviceType }); services.AddSingleton(factoryType, (serviceProvder) => { var pools = serviceProvder.GetService <IZooyardPools>(); var zooyardFactory = factoryType.GetConstructor(new[] { typeof(IZooyardPools), typeof(string), typeof(string) }) .Invoke(new object[] { pools, item.Key, item.Value.Version }); return(zooyardFactory); }); services.AddTransient(serviceType, (serviceProvder) => { var factory = serviceProvder.GetService(factoryType); var result = factory.GetType().GetMethod("CreateYard").Invoke(factory, null); return(result); }); } }