Move to new network concept

pull/1/head
a.bozhenov 5 years ago
parent 697b42ab2c
commit a1f7089b68

@ -1,12 +1,10 @@
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Reflection;
using System.Threading;
using ZeroLevel.Network;
using ZeroLevel.Services.Serialization;
namespace ZeroLevel.Services.Applications
{
@ -121,61 +119,15 @@ namespace ZeroLevel.Services.Applications
#endregion Config
#region Network
private static readonly IRouter _null_router = new NullRouter();
private IDiscoveryClient _discoveryClient = null; // Feature расширить до нескольких discovery
private long _update_discovery_table_task = -1;
private long _register_in_discovery_table_task = -1;
private readonly AliasSet<IPEndPoint> _aliases = new AliasSet<IPEndPoint>();
private static TimeSpan _update_discovery_table_period = TimeSpan.FromSeconds(15);
private static TimeSpan _register_in_discovery_table_period = TimeSpan.FromSeconds(15);
private static readonly ConcurrentDictionary<string, ExClient> _clientInstances = new ConcurrentDictionary<string, ExClient>();
private readonly ConcurrentDictionary<string, SocketServer> _serverInstances = new ConcurrentDictionary<string, SocketServer>();
private void RestartDiscoveryTasks()
{
if (_update_discovery_table_task != -1)
{
Sheduller.Remove(_update_discovery_table_task);
}
if (_register_in_discovery_table_task != -1)
{
Sheduller.Remove(_register_in_discovery_table_task);
}
RegisterServicesInDiscovery();
_update_discovery_table_task = Sheduller.RemindEvery(_update_discovery_table_period, RegisterServicesInDiscovery);
_register_in_discovery_table_task = Sheduller.RemindEvery(_register_in_discovery_table_period, () => { });
}
private void RegisterServicesInDiscovery()
{
var services = _serverInstances.
Values.
Select(s =>
{
var info = MessageSerializer.Copy(this._serviceInfo);
info.Port = s.LocalEndpoint.Port;
return info;
}).
ToList();
foreach (var service in services)
{
_discoveryClient.Register(service);
}
}
private readonly Exchange _exhange = new Exchange();
public void UseDiscovery()
{
if (_state == ZeroServiceStatus.Running
|| _state == ZeroServiceStatus.Initialized)
{
if (_discoveryClient != null)
{
_discoveryClient.Dispose();
_discoveryClient = null;
}
var discovery = Configuration.Default.First("discovery");
_discoveryClient = new DiscoveryClient(GetClient(NetUtils.CreateIPEndPoint(discovery), false, _null_router));
RestartDiscoveryTasks();
_exhange.UseDiscovery();
}
}
@ -184,13 +136,7 @@ namespace ZeroLevel.Services.Applications
if (_state == ZeroServiceStatus.Running
|| _state == ZeroServiceStatus.Initialized)
{
if (_discoveryClient != null)
{
_discoveryClient.Dispose();
_discoveryClient = null;
}
_discoveryClient = new DiscoveryClient(GetClient(NetUtils.CreateIPEndPoint(endpoint), false, _null_router));
RestartDiscoveryTasks();
_exhange.UseDiscovery(endpoint);
}
}
@ -199,13 +145,7 @@ namespace ZeroLevel.Services.Applications
if (_state == ZeroServiceStatus.Running
|| _state == ZeroServiceStatus.Initialized)
{
if (_discoveryClient != null)
{
_discoveryClient.Dispose();
_discoveryClient = null;
}
_discoveryClient = new DiscoveryClient(GetClient(endpoint, false, _null_router));
RestartDiscoveryTasks();
_exhange.UseDiscovery(endpoint);
}
}
@ -214,9 +154,9 @@ namespace ZeroLevel.Services.Applications
if (_state == ZeroServiceStatus.Running
|| _state == ZeroServiceStatus.Initialized)
{
return GetServer(new IPEndPoint(IPAddress.Any, NetUtils.GetFreeTcpPort()), new Router()).Router;
return _exhange.UseHost();
}
return _null_router;
return BaseSocket.NullRouter;
}
public IRouter UseHost(int port)
@ -224,9 +164,9 @@ namespace ZeroLevel.Services.Applications
if (_state == ZeroServiceStatus.Running
|| _state == ZeroServiceStatus.Initialized)
{
return GetServer(new IPEndPoint(IPAddress.Any, port), new Router()).Router;
return _exhange.UseHost(port);
}
return _null_router;
return BaseSocket.NullRouter;
}
public IRouter UseHost(IPEndPoint endpoint)
@ -234,9 +174,9 @@ namespace ZeroLevel.Services.Applications
if (_state == ZeroServiceStatus.Running
|| _state == ZeroServiceStatus.Initialized)
{
return GetServer(endpoint, new Router()).Router;
return _exhange.UseHost(endpoint);
}
return _null_router;
return BaseSocket.NullRouter;
}
public ExClient ConnectToService(string endpoint)
@ -246,7 +186,7 @@ namespace ZeroLevel.Services.Applications
{
if (_aliases.Contains(endpoint))
{
return GetClient(_aliases.GetAddress(endpoint), true);
return GetClient(_aliases.Get(endpoint), true);
}
return GetClient(NetUtils.CreateIPEndPoint(endpoint), true);
}
@ -417,39 +357,6 @@ namespace ZeroLevel.Services.Applications
}
#endregion
public void StoreConnection(string endpoint)
{
if (_state == ZeroServiceStatus.Running ||
_state == ZeroServiceStatus.Initialized)
{
_aliases.Set(endpoint, NetUtils.CreateIPEndPoint(endpoint));
}
}
public void StoreConnection(string alias, string endpoint)
{
if (_state == ZeroServiceStatus.Running ||
_state == ZeroServiceStatus.Initialized)
{
_aliases.Set(alias, NetUtils.CreateIPEndPoint(endpoint));
}
}
public void StoreConnection(IPEndPoint endpoint)
{
if (_state == ZeroServiceStatus.Running ||
_state == ZeroServiceStatus.Initialized)
{
_aliases.Set($"{endpoint.Address}:{endpoint.Port}", endpoint);
}
}
public void StoreConnection(string alias, IPEndPoint endpoint)
{
if (_state == ZeroServiceStatus.Running ||
_state == ZeroServiceStatus.Initialized)
{
_aliases.Set(alias, endpoint);
}
}
#endregion
#region Service control
@ -524,85 +431,12 @@ namespace ZeroLevel.Services.Applications
}
#endregion
#region Utils
private ExClient GetClient(IPEndPoint endpoint, bool use_cachee, IRouter router = null)
{
if (use_cachee)
{
string key = $"{endpoint.Address}:{endpoint.Port}";
ExClient instance = null;
if (_clientInstances.ContainsKey(key))
{
instance = _clientInstances[key];
if (instance.Status == SocketClientStatus.Working)
{
return instance;
}
_clientInstances.TryRemove(key, out instance);
instance.Dispose();
instance = null;
}
instance = new ExClient(new SocketClient(endpoint, router ?? new Router()));
_clientInstances[key] = instance;
return instance;
}
return new ExClient(new SocketClient(endpoint, router ?? new Router()));
}
private SocketServer GetServer(IPEndPoint endpoint, IRouter router)
{
string key = $"{endpoint.Address}:{endpoint.Port}";
if (_serverInstances.ContainsKey(key))
{
return _serverInstances[key];
}
var instance = new SocketServer(endpoint, router);
_serverInstances[key] = instance;
return instance;
}
#endregion
public void Dispose()
{
if (_state != ZeroServiceStatus.Disposed)
{
_state = ZeroServiceStatus.Disposed;
if (_update_discovery_table_task != -1)
{
Sheduller.Remove(_update_discovery_table_task);
}
if (_register_in_discovery_table_task != -1)
{
Sheduller.Remove(_register_in_discovery_table_task);
}
foreach (var client in _clientInstances)
{
try
{
client.Value.Dispose();
}
catch (Exception ex)
{
Log.Error(ex, $"[BaseZeroService`{Name ?? string.Empty}.Dispose()] Dispose SocketClient to endpoint {client.Key}");
}
}
foreach (var server in _serverInstances)
{
try
{
server.Value.Dispose();
}
catch (Exception ex)
{
Log.Error(ex, $"[BaseZeroService`{Name ?? string.Empty}.Dispose()] Dispose SocketServer with endpoint {server.Key}");
}
}
_exhange.Dispose();
}
}
}

@ -23,13 +23,26 @@ namespace ZeroLevel.Services.Collections
public int Count { get { return _collection.Count; } }
public RoundRobinCollection() { }
public RoundRobinCollection(IEnumerable<T> items)
{
if (items != null && items.Any())
{
_collection.AddRange(items);
_index = 0;
}
}
public void Add(T item)
{
_lock.EnterWriteLock();
try
{
_collection.Add(item);
if (_index == -1) _index = 0;
if (!_collection.Contains(item))
{
_collection.Add(item);
if (_index == -1) _index = 0;
}
}
finally
{
@ -121,7 +134,23 @@ namespace ZeroLevel.Services.Collections
public IEnumerable<T> Find(Func<T, bool> selector)
{
return _collection.Where(selector);
_lock.EnterReadLock();
try
{
var arr = new List<T>(_collection.Count);
for (int i = _index; i < _collection.Count; i++)
{
if (selector(_collection[i]))
{
arr.Add(_collection[i]);
}
}
return arr;
}
finally
{
_lock.ExitReadLock();
}
}
public void Clear()

@ -1,73 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace ZeroLevel.Services.Collections
{
public sealed class RoundRobinOverCollection<T>
{
private class Node
{
public T Value;
public Node Next;
}
private int _count;
private Node _currentNode;
public bool IsEmpty => _count <= 0;
public RoundRobinOverCollection(IEnumerable<T> collection)
{
if (collection.Any())
{
_count = 1;
_currentNode = new Node { Value = collection.First() };
var prev = _currentNode;
foreach (var e in collection.Skip(1))
{
prev.Next = new Node { Value = e };
prev = prev.Next;
_count++;
}
prev.Next = _currentNode;
}
else
{
_count = 0;
}
}
public IEnumerable<T> Find(Func<T, bool> selector)
{
if (_count == 0)
{
yield break;
}
var cursor = _currentNode;
for (int i = 0; i < _count; i++)
{
if (selector(cursor.Value))
{
yield return cursor.Value;
}
cursor = cursor.Next;
}
}
public IEnumerable<T> GenerateSeq()
{
if (_count == 0)
{
yield break;
}
var cursor = _currentNode;
_currentNode = _currentNode.Next;
for (int i = 0; i < _count; i++)
{
yield return cursor.Value;
cursor = cursor.Next;
}
}
}
}

@ -130,54 +130,96 @@ namespace ZeroLevel.Network
private readonly ConcurrentDictionary<string, _RoundRobinCollection<T>> _aliases = new ConcurrentDictionary<string, _RoundRobinCollection<T>>();
public bool Contains(string alias) => _aliases.ContainsKey(alias);
public bool Contains(string key) => _aliases.ContainsKey(key);
public void Set(string alias, T address)
public void Append(string key, T address)
{
if (_aliases.ContainsKey(alias) == false)
if (_aliases.ContainsKey(key) == false)
{
if (_aliases.TryAdd(alias, new _RoundRobinCollection<T>()))
if (_aliases.TryAdd(key, new _RoundRobinCollection<T>()))
{
_aliases[alias].Add(address);
_aliases[key].Add(address);
}
}
else
{
_aliases[alias].Add(address);
_aliases[key].Add(address);
}
}
public void Set(string alias, IEnumerable<T> addresses)
public void Append(string key, IEnumerable<T> addresses)
{
if (_aliases.ContainsKey(alias) == false)
if (_aliases.ContainsKey(key) == false)
{
if (_aliases.TryAdd(alias, new _RoundRobinCollection<T>()))
if (_aliases.TryAdd(key, new _RoundRobinCollection<T>()))
{
foreach (var address in addresses)
_aliases[alias].Add(address);
{
_aliases[key].Add(address);
}
}
}
else
{
foreach (var address in addresses)
{
_aliases[key].Add(address);
}
}
}
public void Update(string key, T address)
{
if (_aliases.ContainsKey(key) == false)
{
if (_aliases.TryAdd(key, new _RoundRobinCollection<T>()))
{
_aliases[key].Add(address);
}
}
else
{
_aliases[key].Clear();
_aliases[key].Add(address);
}
}
public void Update(string key, IEnumerable<T> addresses)
{
if (_aliases.ContainsKey(key) == false)
{
if (_aliases.TryAdd(key, new _RoundRobinCollection<T>()))
{
foreach (var address in addresses)
{
_aliases[key].Add(address);
}
}
}
else
{
_aliases[key].Clear();
foreach (var address in addresses)
_aliases[alias].Add(address);
{
_aliases[key].Add(address);
}
}
}
public T GetAddress(string alias)
public T Get(string key)
{
if (_aliases.ContainsKey(alias) && _aliases[alias].MoveNext())
if (_aliases.ContainsKey(key) && _aliases[key].MoveNext())
{
return _aliases[alias].Current;
return _aliases[key].Current;
}
return default(T);
}
public IEnumerable<T> GetAddresses(string alias)
public IEnumerable<T> GetAll(string key)
{
if (_aliases.ContainsKey(alias) && _aliases[alias].MoveNext())
if (_aliases.ContainsKey(key) && _aliases[key].MoveNext())
{
return _aliases[alias].GetCurrentSeq();
return _aliases[key].GetCurrentSeq();
}
return Enumerable.Empty<T>();
}

@ -9,6 +9,8 @@ namespace ZeroLevel.Network
MAX_FRAME_PAYLOAD_SIZE = Configuration.Default.FirstOrDefault<int>("MAX_FRAME_PAYLOAD_SIZE", DEFAULT_MAX_FRAME_PAYLOAD_SIZE);
}
public static readonly IRouter NullRouter = new NullRouter();
public const string DEFAULT_MESSAGE_INBOX = "__message_inbox__";
public const string DEFAULT_REQUEST_INBOX = "__request_inbox__";
public const string DEFAULT_REQUEST_WITHOUT_ARGS_INBOX = "__request_no_args_inbox__";

@ -6,39 +6,39 @@ namespace ZeroLevel.Network
{
public interface IClientSet
{
InvokeResult Send<T>(string alias, T data);
InvokeResult Send<T>(string alias, string inbox, T data);
InvokeResult Request<Tresponse>(string alias, Action<Tresponse> callback);
InvokeResult Request<Tresponse>(string alias, string inbox, Action<Tresponse> callback);
InvokeResult Request<Trequest, Tresponse>(string alias, Trequest request, Action<Tresponse> callback);
InvokeResult Request<Trequest, Tresponse>(string alias, string inbox, Trequest request, Action<Tresponse> callback);
InvokeResult SendBroadcast<T>(string alias, T data);
InvokeResult SendBroadcast<T>(string alias, string inbox, T data);
InvokeResult SendBroadcastByType<T>(string serviceType, T data);
InvokeResult SendBroadcastByType<T>(string serviceType, string inbox, T data);
InvokeResult SendBroadcastByGroup<T>(string serviceGroup, T data);
InvokeResult SendBroadcastByGroup<T>(string serviceGroup, string inbox, T data);
InvokeResult RequestBroadcast<Tresponse>(string alias, Action<IEnumerable<Tresponse>> callback);
InvokeResult RequestBroadcast<Tresponse>(string alias, string inbox, Action<IEnumerable<Tresponse>> callback);
InvokeResult RequestBroadcast<Trequest, Tresponse>(string alias, Trequest data, Action<IEnumerable<Tresponse>> callback);
InvokeResult RequestBroadcast<Trequest, Tresponse>(string alias, string inbox, Trequest data, Action<IEnumerable<Tresponse>> callback);
InvokeResult RequestBroadcastByType<Tresponse>(string serviceType, Action<IEnumerable<Tresponse>> callback);
InvokeResult RequestBroadcastByType<Tresponse>(string serviceType, string inbox, Action<IEnumerable<Tresponse>> callback);
InvokeResult RequestBroadcastByType<Trequest, Tresponse>(string serviceType, Trequest data, Action<IEnumerable<Tresponse>> callback);
InvokeResult RequestBroadcastByType<Trequest, Tresponse>(string serviceType, string inbox, Trequest data, Action<IEnumerable<Tresponse>> callback);
InvokeResult RequestBroadcastByGroup<Tresponse>(string serviceGroup, Action<IEnumerable<Tresponse>> callback);
InvokeResult RequestBroadcastByGroup<Tresponse>(string serviceGroup, string inbox, Action<IEnumerable<Tresponse>> callback);
InvokeResult RequestBroadcastByGroup<Trequest, Tresponse>(string serviceGroup, Trequest data, Action<IEnumerable<Tresponse>> callback);
InvokeResult RequestBroadcastByGroup<Trequest, Tresponse>(string serviceGroup, string inbox, Trequest data, Action<IEnumerable<Tresponse>> callback);
bool Send<T>(string alias, T data);
bool Send<T>(string alias, string inbox, T data);
bool Request<Tresponse>(string alias, Action<Tresponse> callback);
bool Request<Tresponse>(string alias, string inbox, Action<Tresponse> callback);
bool Request<Trequest, Tresponse>(string alias, Trequest request, Action<Tresponse> callback);
bool Request<Trequest, Tresponse>(string alias, string inbox, Trequest request, Action<Tresponse> callback);
bool SendBroadcast<T>(string alias, T data);
bool SendBroadcast<T>(string alias, string inbox, T data);
bool SendBroadcastByType<T>(string serviceType, T data);
bool SendBroadcastByType<T>(string serviceType, string inbox, T data);
bool SendBroadcastByGroup<T>(string serviceGroup, T data);
bool SendBroadcastByGroup<T>(string serviceGroup, string inbox, T data);
bool RequestBroadcast<Tresponse>(string alias, Action<IEnumerable<Tresponse>> callback);
bool RequestBroadcast<Tresponse>(string alias, string inbox, Action<IEnumerable<Tresponse>> callback);
bool RequestBroadcast<Trequest, Tresponse>(string alias, Trequest data, Action<IEnumerable<Tresponse>> callback);
bool RequestBroadcast<Trequest, Tresponse>(string alias, string inbox, Trequest data, Action<IEnumerable<Tresponse>> callback);
bool RequestBroadcastByType<Tresponse>(string serviceType, Action<IEnumerable<Tresponse>> callback);
bool RequestBroadcastByType<Tresponse>(string serviceType, string inbox, Action<IEnumerable<Tresponse>> callback);
bool RequestBroadcastByType<Trequest, Tresponse>(string serviceType, Trequest data, Action<IEnumerable<Tresponse>> callback);
bool RequestBroadcastByType<Trequest, Tresponse>(string serviceType, string inbox, Trequest data, Action<IEnumerable<Tresponse>> callback);
bool RequestBroadcastByGroup<Tresponse>(string serviceGroup, Action<IEnumerable<Tresponse>> callback);
bool RequestBroadcastByGroup<Tresponse>(string serviceGroup, string inbox, Action<IEnumerable<Tresponse>> callback);
bool RequestBroadcastByGroup<Trequest, Tresponse>(string serviceGroup, Trequest data, Action<IEnumerable<Tresponse>> callback);
bool RequestBroadcastByGroup<Trequest, Tresponse>(string serviceGroup, string inbox, Trequest data, Action<IEnumerable<Tresponse>> callback);
}
}

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using ZeroLevel.Models;
using ZeroLevel.Services.Collections;
@ -17,9 +18,9 @@ namespace ZeroLevel.Network
private IEnumerable<ServiceEndpointInfo> _empty = Enumerable.Empty<ServiceEndpointInfo>();
private List<ServiceEndpointInfo> _services = new List<ServiceEndpointInfo>();
private Dictionary<string, RoundRobinOverCollection<ServiceEndpointInfo>> _tableByKey;
private Dictionary<string, RoundRobinOverCollection<ServiceEndpointInfo>> _tableByGroups;
private Dictionary<string, RoundRobinOverCollection<ServiceEndpointInfo>> _tableByTypes;
private Dictionary<string, RoundRobinCollection<ServiceEndpointInfo>> _tableByKey;
private Dictionary<string, RoundRobinCollection<ServiceEndpointInfo>> _tableByGroups;
private Dictionary<string, RoundRobinCollection<ServiceEndpointInfo>> _tableByTypes;
internal void Update(IEnumerable<ServiceEndpointsInfo> records)
{
@ -40,9 +41,9 @@ namespace ZeroLevel.Network
try
{
_services = services;
_tableByKey = _services.GroupBy(r => r.Key).ToDictionary(g => g.Key, g => new RoundRobinOverCollection<ServiceEndpointInfo>(g));
_tableByTypes = _services.GroupBy(r => r.Type).ToDictionary(g => g.Key, g => new RoundRobinOverCollection<ServiceEndpointInfo>(g));
_tableByGroups = _services.GroupBy(r => r.Group).ToDictionary(g => g.Key, g => new RoundRobinOverCollection<ServiceEndpointInfo>(g));
_tableByKey = _services.GroupBy(r => r.Key).ToDictionary(g => g.Key, g => new RoundRobinCollection<ServiceEndpointInfo>(g));
_tableByTypes = _services.GroupBy(r => r.Type).ToDictionary(g => g.Key, g => new RoundRobinCollection<ServiceEndpointInfo>(g));
_tableByGroups = _services.GroupBy(r => r.Group).ToDictionary(g => g.Key, g => new RoundRobinCollection<ServiceEndpointInfo>(g));
}
catch (Exception ex)
{
@ -60,7 +61,7 @@ namespace ZeroLevel.Network
_lock.EnterReadLock();
try
{
if (_tableByKey.ContainsKey(key) && !_tableByKey[key].IsEmpty)
if (_tableByKey.ContainsKey(key) && _tableByKey[key].Count > 0)
{
return _tableByKey[key].Find(s => s.Endpoint.Equals(endpoint, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
}
@ -78,9 +79,9 @@ namespace ZeroLevel.Network
_lock.EnterReadLock();
try
{
if (_tableByKey.ContainsKey(key) && !_tableByKey[key].IsEmpty)
if (_tableByKey.ContainsKey(key) && _tableByKey[key].Count > 0)
{
return _tableByKey[key].GenerateSeq();
return _tableByKey[key].GetCurrentSeq();
}
}
finally
@ -96,9 +97,9 @@ namespace ZeroLevel.Network
_lock.EnterReadLock();
try
{
if (_tableByGroups.ContainsKey(group) && !_tableByGroups[group].IsEmpty)
if (_tableByGroups.ContainsKey(group) && _tableByGroups[group].Count > 0)
{
return _tableByGroups[group].GenerateSeq();
return _tableByGroups[group].GetCurrentSeq();
}
}
finally
@ -114,9 +115,9 @@ namespace ZeroLevel.Network
_lock.EnterReadLock();
try
{
if (_tableByTypes.ContainsKey(type) && !_tableByTypes[type].IsEmpty)
if (_tableByTypes.ContainsKey(type) && _tableByTypes[type].Count > 0)
{
return _tableByTypes[type].GenerateSeq();
return _tableByTypes[type].GetCurrentSeq();
}
}
finally

@ -8,195 +8,6 @@ using ZeroLevel.Services.Serialization;
namespace ZeroLevel.Network
{
public sealed class ExClientSet
: IClientSet, IDisposable
{
public void Dispose()
{
throw new NotImplementedException();
}
#region IMultiClient
public InvokeResult Request<Tresponse>(string alias, Action<Tresponse> callback)
{
throw new NotImplementedException();
}
public InvokeResult Request<Tresponse>(string alias, string inbox, Action<Tresponse> callback)
{
throw new NotImplementedException();
}
public InvokeResult Request<Trequest, Tresponse>(string alias, Trequest request, Action<Tresponse> callback)
{
throw new NotImplementedException();
}
public InvokeResult Request<Trequest, Tresponse>(string alias, string inbox, Trequest request, Action<Tresponse> callback)
{
throw new NotImplementedException();
}
public InvokeResult RequestBroadcast<Tresponse>(string alias, Action<IEnumerable<Tresponse>> callback)
{
throw new NotImplementedException();
}
public InvokeResult RequestBroadcast<Tresponse>(string alias, string inbox, Action<IEnumerable<Tresponse>> callback)
{
throw new NotImplementedException();
}
public InvokeResult RequestBroadcast<Trequest, Tresponse>(string alias, Trequest data, Action<IEnumerable<Tresponse>> callback)
{
throw new NotImplementedException();
}
public InvokeResult RequestBroadcast<Trequest, Tresponse>(string alias, string inbox, Trequest data, Action<IEnumerable<Tresponse>> callback)
{
throw new NotImplementedException();
}
public InvokeResult RequestBroadcastByGroup<Tresponse>(string serviceGroup, Action<IEnumerable<Tresponse>> callback)
{
throw new NotImplementedException();
}
public InvokeResult RequestBroadcastByGroup<Tresponse>(string serviceGroup, string inbox, Action<IEnumerable<Tresponse>> callback)
{
throw new NotImplementedException();
}
public InvokeResult RequestBroadcastByGroup<Trequest, Tresponse>(string serviceGroup, Trequest data, Action<IEnumerable<Tresponse>> callback)
{
throw new NotImplementedException();
}
public InvokeResult RequestBroadcastByGroup<Trequest, Tresponse>(string serviceGroup, string inbox, Trequest data, Action<IEnumerable<Tresponse>> callback)
{
throw new NotImplementedException();
}
public InvokeResult RequestBroadcastByType<Tresponse>(string serviceType, Action<IEnumerable<Tresponse>> callback)
{
throw new NotImplementedException();
}
public InvokeResult RequestBroadcastByType<Tresponse>(string serviceType, string inbox, Action<IEnumerable<Tresponse>> callback)
{
throw new NotImplementedException();
}
public InvokeResult RequestBroadcastByType<Trequest, Tresponse>(string serviceType, Trequest data, Action<IEnumerable<Tresponse>> callback)
{
throw new NotImplementedException();
}
public InvokeResult RequestBroadcastByType<Trequest, Tresponse>(string serviceType, string inbox, Trequest data, Action<IEnumerable<Tresponse>> callback)
{
throw new NotImplementedException();
}
public InvokeResult Send<T>(string alias, T data)
{
throw new NotImplementedException();
}
public InvokeResult Send<T>(string alias, string inbox, T data)
{
throw new NotImplementedException();
}
public InvokeResult SendBroadcast<T>(string alias, T data)
{
throw new NotImplementedException();
}
public InvokeResult SendBroadcast<T>(string alias, string inbox, T data)
{
throw new NotImplementedException();
}
public InvokeResult SendBroadcastByGroup<T>(string serviceGroup, T data)
{
throw new NotImplementedException();
}
public InvokeResult SendBroadcastByGroup<T>(string serviceGroup, string inbox, T data)
{
throw new NotImplementedException();
}
public InvokeResult SendBroadcastByType<T>(string serviceType, T data)
{
throw new NotImplementedException();
}
public InvokeResult SendBroadcastByType<T>(string serviceType, string inbox, T data)
{
throw new NotImplementedException();
}
#endregion
#region Private
private IEnumerable<Tresp> _RequestBroadcast<Treq, Tresp>(List<ExClient> clients, string inbox, Treq data)
{
var response = new List<Tresp>();
using (var waiter = new CountdownEvent(clients.Count))
{
foreach (var client in clients)
{
Task.Run(() =>
{
try
{
if (false == client.Request<Treq, Tresp>(inbox, data, resp => { waiter.Signal(); response.Add(resp); }).Success)
{
waiter.Signal();
}
}
catch (Exception ex)
{
Log.SystemError(ex, $"[ExClientSet._RequestBroadcast] Error direct request to service '{client.EndPoint}' in broadcast request. Inbox '{inbox}'");
waiter.Signal();
}
});
}
waiter.Wait(BaseSocket.MAX_REQUEST_TIME_MS);
}
return response;
}
private IEnumerable<Tresp> _RequestBroadcast<Tresp>(List<ExClient> clients, string inbox)
{
var response = new List<Tresp>();
using (var waiter = new CountdownEvent(clients.Count))
{
foreach (var client in clients)
{
Task.Run(() =>
{
try
{
if (false == client.Request<Tresp>(inbox, resp => { waiter.Signal(); response.Add(resp); }).Success)
{
waiter.Signal();
}
}
catch (Exception ex)
{
Log.SystemError(ex, $"[ExClientSet._RequestBroadcast] Error direct request to service '{client.EndPoint}' in broadcast request. Inbox '{inbox}'");
waiter.Signal();
}
});
}
waiter.Wait(BaseSocket.MAX_REQUEST_TIME_MS);
}
return response;
}
#endregion
}
public sealed class ExClient
: IClient, IDisposable
{

@ -1,229 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace ZeroLevel.Network
{
/*
public sealed class ExServiceHost
: IDisposable
{
#region Transport helpers
/// <summary>
/// Call service with round-robin balancing
/// </summary>
/// <param name="serviceKey">Service key</param>
/// <param name="callHandler">Service call code</param>
/// <returns>true - service called succesfully</returns>
internal bool CallService(string serviceKey, Func<string, IExClient, bool> callHandler)
{
if (_disposed) return false;
List<ServiceEndpointInfo> candidates;
try
{
candidates = _discoveryClient.GetServiceEndpoints(serviceKey)?.ToList();
}
catch (Exception ex)
{
Log.SystemError(ex, $"[ExServiceHost] Error when trying get endpoints for service key '{serviceKey}'");
return false;
}
if (candidates == null || candidates.Any() == false)
{
Log.Debug($"[ExServiceHost] Not found endpoints for service key '{serviceKey}'");
return false;
}
var success = false;
foreach (var service in candidates)
{
IExClient transport;
try
{
transport = ExchangeTransportFactory.GetClientWithCache(service.Endpoint);
}
catch (Exception ex)
{
Log.SystemError(ex, $"[ExServiceHost] Can't get transport for service '{serviceKey}'");
continue;
}
try
{
success = callHandler(service.Endpoint, transport);
}
catch (Exception ex)
{
Log.SystemError(ex, $"[ExServiceHost] Error send/request data in service '{serviceKey}'. Endpoint '{service.Endpoint}'");
success = false;
}
if (success)
{
break;
}
}
return success;
}
internal bool CallServiceDirect(string endpoint, string serviceKey, Func<IExClient, bool> callHandler)
{
if (_disposed) return false;
ServiceEndpointInfo candidate = null;
try
{
candidate = _discoveryClient.GetService(serviceKey, endpoint);
}
catch (Exception ex)
{
Log.SystemError(ex, $"[ExServiceHost] Error when trying get service info by key '{serviceKey}' and endpoint '{endpoint}'");
return false;
}
if (candidate == null)
{
Log.Debug($"[ExServiceHost] Not found service info for key '{serviceKey}' and endpoint '{endpoint}'");
return false;
}
IExClient transport;
try
{
transport = ExchangeTransportFactory.GetClientWithCache(candidate.Endpoint);
}
catch (Exception ex)
{
Log.SystemError(ex, $"[ExServiceHost] Can't get transport for service '{serviceKey}'");
return false;
}
return callHandler(transport);
}
internal IEnumerable<IExClient> GetClientEnumerator(string serviceKey)
{
if (!_disposed)
{
List<ServiceEndpointInfo> candidates;
try
{
candidates = _discoveryClient.GetServiceEndpoints(serviceKey)?.ToList();
}
catch (Exception ex)
{
Log.SystemError(ex, $"[Exchange] Error when trying get endpoints for service key '{serviceKey}'");
candidates = null;
}
if (candidates != null && candidates.Any())
{
foreach (var service in candidates)
{
IExClient transport;
try
{
transport = ExchangeTransportFactory.GetClientWithCache(service.Endpoint);
}
catch (Exception ex)
{
Log.SystemError(ex, $"[Exchange] Can't get transport for endpoint '{service.Endpoint}'");
continue;
}
yield return transport;
}
}
else
{
Log.Debug($"[Exchange] Not found endpoints for service key '{serviceKey}'");
}
}
}
internal IEnumerable<IExClient> GetClientEnumeratorByType(string serviceType)
{
if (!_disposed)
{
List<ServiceEndpointInfo> candidates;
try
{
candidates = _discoveryClient.GetServiceEndpointsByType(serviceType)?.ToList();
}
catch (Exception ex)
{
Log.SystemError(ex, $"[Exchange] Error when trying get endpoints for service type '{serviceType}'");
candidates = null;
}
if (candidates != null && candidates.Any())
{
foreach (var service in candidates)
{
IExClient transport;
try
{
transport = ExchangeTransportFactory.GetClientWithCache(service.Endpoint);
}
catch (Exception ex)
{
Log.SystemError(ex, $"[Exchange] Can't get transport for endpoint '{service.Endpoint}'");
continue;
}
yield return transport;
}
}
else
{
Log.Debug($"[Exchange] Not found endpoints for service type '{serviceType}'");
}
}
}
internal IEnumerable<IExClient> GetClientEnumeratorByGroup(string serviceGroup)
{
if (!_disposed)
{
List<ServiceEndpointInfo> candidates;
try
{
candidates = _discoveryClient.GetServiceEndpointsByGroup(serviceGroup)?.ToList();
}
catch (Exception ex)
{
Log.SystemError(ex, $"[Exchange] Error when trying get endpoints for service group '{serviceGroup}'");
candidates = null;
}
if (candidates != null && candidates.Any())
{
foreach (var service in candidates)
{
IExClient transport;
try
{
transport = ExchangeTransportFactory.GetClientWithCache(service.Endpoint);
}
catch (Exception ex)
{
Log.SystemError(ex, $"[Exchange] Can't get transport for endpoint '{service.Endpoint}'");
continue;
}
yield return transport;
}
}
else
{
Log.Debug($"[Exchange] Not found endpoints for service group '{serviceGroup}'");
}
}
}
#endregion Transport helpers
public void Dispose()
{
if (_disposed) return;
_disposed = true;
Sheduller.Remove(_registerTaskKey);
foreach (var s in _services)
{
s.Value.Server.Dispose();
}
}
}
*/
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,255 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using ZeroLevel.Models;
using ZeroLevel.Services.Collections;
namespace ZeroLevel.Network
{
/*
One IPEndpoint binded with one service.
Service can have one key, one type, one group.
Therefore IPEndpoint can be binded with one key, one type and one group.
One key can refer to many IPEndPoints.
One type can refer to many IPEndPoints.
One group can refer to many IPEndPoints.
*/
public sealed class ServiceRouteStorage
{
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
private Dictionary<string, RoundRobinCollection<IPEndPoint>> _tableByKey
= new Dictionary<string, RoundRobinCollection<IPEndPoint>>();
private Dictionary<string, RoundRobinCollection<IPEndPoint>> _tableByGroups
= new Dictionary<string, RoundRobinCollection<IPEndPoint>>();
private Dictionary<string, RoundRobinCollection<IPEndPoint>> _tableByTypes
= new Dictionary<string, RoundRobinCollection<IPEndPoint>>();
private Dictionary<IPEndPoint, string[]> _endpoints
= new Dictionary<IPEndPoint, string[]>();
public void Set(IPEndPoint endpoint)
{
_lock.EnterWriteLock();
try
{
var key = $"{endpoint.Address}:{endpoint.Port}";
if (_endpoints.ContainsKey(endpoint))
{
if (_tableByKey.ContainsKey(key))
{
return;
}
Remove(endpoint);
}
AppendByKeys(key, endpoint);
_endpoints.Add(endpoint, new string[3] { $"{endpoint.Address}:{endpoint.Port}", null, null });
}
finally
{
_lock.ExitWriteLock();
}
}
public void Set(IEnumerable<IPEndPoint> endpoints)
{
foreach (var ep in endpoints)
{
Set(ep);
}
}
public void Set(string key, IPEndPoint endpoint)
{
_lock.EnterWriteLock();
try
{
if (_endpoints.ContainsKey(endpoint))
{
var exists = _endpoints[endpoint];
if (exists[0] != null
&& _tableByKey.ContainsKey(exists[0])
&& _tableByKey[exists[0]].Count == 1
&& _tableByKey[exists[0]].Contains(endpoint))
{
return;
}
Remove(endpoint);
}
AppendByKeys(key, endpoint);
_endpoints.Add(endpoint, new string[3] { key, null, null });
}
finally
{
_lock.ExitWriteLock();
}
}
public void Set(string key, IEnumerable<IPEndPoint> endpoints)
{
_lock.EnterWriteLock();
try
{
if (_tableByKey.ContainsKey(key))
{
if (_tableByKey[key].Source.OrderingEquals(endpoints))
{
return;
}
var drop = _tableByKey[key].Source.ToArray();
for (int i = 0; i < drop.Length; i++)
{
Remove(drop[i]);
}
}
foreach (var ep in endpoints)
{
_endpoints.Add(ep, new string[3] { key, null, null });
AppendByKeys(key, ep);
}
}
finally
{
_lock.ExitWriteLock();
}
}
public void Set(string key, string type, string group, IPEndPoint endpoint)
{
_lock.EnterWriteLock();
try
{
Remove(endpoint);
if (key == null)
{
key = $"{endpoint.Address}:{endpoint.Port}";
}
AppendByKeys(key, endpoint);
if (type != null)
{
AppendByType(key, endpoint);
}
if (group != null)
{
AppendByGroup(key, endpoint);
}
_endpoints.Add(endpoint, new string[3] { key, null, null });
}
finally
{
_lock.ExitWriteLock();
}
}
public void Set(string key, string type, string group, IEnumerable<IPEndPoint> endpoints)
{
_lock.EnterWriteLock();
try
{
foreach (var ep in endpoints)
{
Remove(ep);
Set(key, type, group, ep);
}
}
finally
{
_lock.ExitWriteLock();
}
}
#region GET
public InvokeResult<IPEndPoint> Get(string key)
{
if (_tableByKey.ContainsKey(key))
{
if (_tableByKey[key].MoveNext())
return InvokeResult.Succeeding(_tableByKey[key].Current);
}
return InvokeResult.Fault<IPEndPoint>($"No endpoints by key '{key}'");
}
public InvokeResult<IEnumerable<IPEndPoint>> GetAll(string key)
{
if (_tableByKey.ContainsKey(key))
{
if (_tableByKey[key].MoveNext())
return InvokeResult.Succeeding(_tableByKey[key].GetCurrentSeq());
}
return InvokeResult.Fault<IEnumerable<IPEndPoint>>($"No endpoints by key '{key}'");
}
public InvokeResult<IPEndPoint> GetByType(string type)
{
if (_tableByTypes.ContainsKey(type))
{
if (_tableByTypes[type].MoveNext())
return InvokeResult.Succeeding(_tableByTypes[type].Current);
}
return InvokeResult.Fault<IPEndPoint>($"No endpoints by type '{type}'");
}
public InvokeResult<IEnumerable<IPEndPoint>> GetAllByType(string type)
{
if (_tableByTypes.ContainsKey(type))
{
if (_tableByTypes[type].MoveNext())
return InvokeResult.Succeeding(_tableByTypes[type].GetCurrentSeq());
}
return InvokeResult.Fault<IEnumerable<IPEndPoint>>($"No endpoints by type '{type}'");
}
public InvokeResult<IPEndPoint> GetByGroup(string group)
{
if (_tableByGroups.ContainsKey(group))
{
if (_tableByGroups[group].MoveNext())
return InvokeResult.Succeeding(_tableByGroups[group].Current);
}
return InvokeResult.Fault<IPEndPoint>($"No endpoints by group '{group}'");
}
public InvokeResult<IEnumerable<IPEndPoint>> GetAllByGroup(string group)
{
if (_tableByGroups.ContainsKey(group))
{
if (_tableByGroups[group].MoveNext())
return InvokeResult.Succeeding(_tableByGroups[group].GetCurrentSeq());
}
return InvokeResult.Fault<IEnumerable<IPEndPoint>>($"No endpoints by group '{group}'");
}
#endregion
#region Private
private void AppendByKeys(string key, IPEndPoint endpoint)
{
Append(key, endpoint, _tableByKey);
}
private void AppendByType(string type, IPEndPoint endpoint)
{
Append(type, endpoint, _tableByTypes);
}
private void AppendByGroup(string group, IPEndPoint endpoint)
{
Append(group, endpoint, _tableByGroups);
}
private void Append(string key, IPEndPoint value, Dictionary<string, RoundRobinCollection<IPEndPoint>> dict)
{
if (!dict.ContainsKey(key))
{
dict.Add(key, new RoundRobinCollection<IPEndPoint>());
}
dict[key].Add(value);
}
private void Remove(IPEndPoint endpoint)
{
var refs = _endpoints[endpoint];
if (refs[0] != null && _tableByKey.ContainsKey(refs[0])) _tableByKey[refs[0]].Remove(endpoint);
if (refs[1] != null && _tableByTypes.ContainsKey(refs[1])) _tableByTypes[refs[1]].Remove(endpoint);
if (refs[2] != null && _tableByGroups.ContainsKey(refs[2])) _tableByGroups[refs[2]].Remove(endpoint);
_endpoints.Remove(endpoint);
}
#endregion
}
}

@ -0,0 +1,84 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Net;
namespace ZeroLevel.Network
{
internal sealed class ExClientServerCachee
: IDisposable
{
private static readonly ConcurrentDictionary<string, ExClient> _clientInstances = new ConcurrentDictionary<string, ExClient>();
private readonly ConcurrentDictionary<string, SocketServer> _serverInstances = new ConcurrentDictionary<string, SocketServer>();
private HashSet<string> _clients = new HashSet<string>();
public ExClient GetClient(IPEndPoint endpoint, bool use_cachee, IRouter router = null)
{
if (use_cachee)
{
string key = $"{endpoint.Address}:{endpoint.Port}";
ExClient instance = null;
if (_clientInstances.ContainsKey(key))
{
instance = _clientInstances[key];
if (instance.Status == SocketClientStatus.Working)
{
return instance;
}
_clientInstances.TryRemove(key, out instance);
instance.Dispose();
instance = null;
}
instance = new ExClient(new SocketClient(endpoint, router ?? new Router()));
_clientInstances[key] = instance;
return instance;
}
return new ExClient(new SocketClient(endpoint, router ?? new Router()));
}
public SocketServer GetServer(IPEndPoint endpoint, IRouter router)
{
string key = $"{endpoint.Address}:{endpoint.Port}";
if (_serverInstances.ContainsKey(key))
{
return _serverInstances[key];
}
var instance = new SocketServer(endpoint, router);
_serverInstances[key] = instance;
return instance;
}
public void Dispose()
{
ExClient removed;
foreach (var client in _clients)
{
try
{
if (_clientInstances.TryRemove(client, out removed))
{
removed.Dispose();
}
}
catch (Exception ex)
{
Log.Error(ex, $"[ExClientServerCachee.Dispose()] Dispose SocketClient to endpoint {client}");
}
}
_clients.Clear();
foreach (var server in _serverInstances)
{
try
{
server.Value.Dispose();
}
catch (Exception ex)
{
Log.Error(ex, $"[ExClientServerCachee.Dispose()] Dispose SocketServer with endpoint {server.Key}");
}
}
_serverInstances.Clear();
}
}
}
Loading…
Cancel
Save

Powered by TurnKey Linux.