diff --git a/Shemes/Network.graphml b/Shemes/Network.graphml new file mode 100644 index 0000000..9bcb6a4 --- /dev/null +++ b/Shemes/Network.graphml @@ -0,0 +1,687 @@ + + + + + + + + + + + + + + + + + + + + + + + + NetworkStreamFastObfuscator + + + + + + + + + + + ExchangeTransportFactory + + + + + + + + + + + IExService + + + + + + + + + + + IExClient + + + + + + + + + + + ZBaseNetwork + + + + + + + + + + + ZSocketClient + + + + + + + + + + + ZSocketServer + + + + + + + + + + + <ZSocketServerClient> + + + + + + + + + + + IZTransport + + + + + + + + + + + + + + ExClient + + + + + + + + + + + IExClient + + + + + + + + + + + + + + IZBackward + + + + + + + + + + + + + + ExRouter + + + + + + + + + + + ExService + + + + + + + + + + + IExService + + + + + + + + + + + + + + IZObservableServer + + + + + + + + + + + + + + FrameExchange + + + + + + + + + + + FrameBuilder + + + + + + + + + + + FrameParser + + + + + + + + + + + ZExSocketObservableServer + + + + + + + + + + + ExServiceHost + + + + + + + + + + + IDiscoveryClient + + + + + + + + + + + + + + IExchangeService + + + + + + + + + + + + + + RegisterService + + + + + + + + + + + RegisterService + + + + + + + + + + + MicroserviceInfo + + + + + + + + + + + DiscoveryClient + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ZeroLevel.Discovery/App.config b/ZeroLevel.Discovery/App.config index f91f31e..8ac5084 100644 --- a/ZeroLevel.Discovery/App.config +++ b/ZeroLevel.Discovery/App.config @@ -5,7 +5,8 @@ - + + diff --git a/ZeroLevel.Discovery/DiscoveryService.cs b/ZeroLevel.Discovery/DiscoveryService.cs index f48cf3c..5665a7c 100644 --- a/ZeroLevel.Discovery/DiscoveryService.cs +++ b/ZeroLevel.Discovery/DiscoveryService.cs @@ -1,10 +1,18 @@ -using ZeroLevel.Services.Applications; +using System.Collections; +using System.Collections.Generic; +using ZeroLevel.Models; +using ZeroLevel.Network; +using ZeroLevel.Network.Microservices; +using ZeroLevel.Services.Applications; +using ZeroLevel.Services.Network; namespace ZeroLevel.Discovery { public sealed class DiscoveryService : BaseWindowsService, IZeroService { + private IExService _exInbox; + public DiscoveryService() : base("Discovery") { @@ -20,13 +28,23 @@ namespace ZeroLevel.Discovery public override void StartAction() { - Injector.Default.Register(new RouteTable()); - var port = Configuration.Default.First("port"); + var routeTable = new RouteTable(); + + Injector.Default.Register(routeTable); + var port = Configuration.Default.First("apiport"); Startup.StartWebPanel(port, false); + + var socketPort = Configuration.Default.First("socketport"); + _exInbox = ExchangeTransportFactory.GetServer("socket", socketPort); + _exInbox.RegisterInbox>("services", (_, __) => routeTable.Get()); + _exInbox.RegisterInbox("register", (info, _, __) => routeTable.Append(info)); + + Log.Info($"TCP server started on port {socketPort}"); } public override void StopAction() { + _exInbox.Dispose(); } } } \ No newline at end of file diff --git a/ZeroLevel.Discovery/RouteTable.cs b/ZeroLevel.Discovery/RouteTable.cs index 699dfbe..2d46f5d 100644 --- a/ZeroLevel.Discovery/RouteTable.cs +++ b/ZeroLevel.Discovery/RouteTable.cs @@ -4,8 +4,8 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; -using ZeroLevel.Microservices; using ZeroLevel.Models; +using ZeroLevel.Network; using ZeroLevel.Network.Microservices; namespace ZeroLevel.Discovery diff --git a/ZeroLevel.Discovery/ZeroLevel.Discovery.csproj b/ZeroLevel.Discovery/ZeroLevel.Discovery.csproj index 299b78e..3028b5e 100644 --- a/ZeroLevel.Discovery/ZeroLevel.Discovery.csproj +++ b/ZeroLevel.Discovery/ZeroLevel.Discovery.csproj @@ -77,7 +77,6 @@ Component - diff --git a/ZeroLevel.Discovery/obj/Debug/ZeroLevel.Discovery.csproj.CoreCompileInputs.cache b/ZeroLevel.Discovery/obj/Debug/ZeroLevel.Discovery.csproj.CoreCompileInputs.cache index ffd6fd9..8950e52 100644 --- a/ZeroLevel.Discovery/obj/Debug/ZeroLevel.Discovery.csproj.CoreCompileInputs.cache +++ b/ZeroLevel.Discovery/obj/Debug/ZeroLevel.Discovery.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -4f0bbfe8ac44b56784f7eeaa3cdef96609d6b97e +fe8032ac49bedc0ec84767ee0419b2fc618b5766 diff --git a/ZeroLevel.Discovery/obj/Debug/ZeroLevel.Discovery.csprojAssemblyReference.cache b/ZeroLevel.Discovery/obj/Debug/ZeroLevel.Discovery.csprojAssemblyReference.cache index dca3baa..7e437ec 100644 Binary files a/ZeroLevel.Discovery/obj/Debug/ZeroLevel.Discovery.csprojAssemblyReference.cache and b/ZeroLevel.Discovery/obj/Debug/ZeroLevel.Discovery.csprojAssemblyReference.cache differ diff --git a/ZeroLevel.Microservices/BaseProxy.cs b/ZeroLevel.Microservices/BaseProxy.cs deleted file mode 100644 index 5b2d19f..0000000 --- a/ZeroLevel.Microservices/BaseProxy.cs +++ /dev/null @@ -1,154 +0,0 @@ -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Text; - -namespace ZeroLevel.ProxyREST -{ - public abstract class BaseProxy - { - private readonly string _baseUrl; - - private Uri BuildRequestUrl(string baseUri, string resource, IDictionary parameters) - { - if (null == resource) throw new ArgumentNullException("resource"); - var stringBuilder = new StringBuilder(baseUri); - if (baseUri[baseUri.Length - 1] != '/') - stringBuilder.Append('/'); - if (resource[0] != '/') - { - stringBuilder.Append(resource); - } - else - { - stringBuilder.Append(resource.Substring(1)); - } - parameters. - Do(list => - { - if (list.Count > 0) - { - stringBuilder.Append("?"); - foreach (string key in list.Keys) - { - var val = list[key]; - if (val == null) - { - stringBuilder.Append(key); - } - else - { - var vtype = val.GetType(); - if (vtype.IsArray) - { - if (vtype.GetElementType() == typeof(string)) - { - var arr = (string[])val; - stringBuilder.Append(string.Join("&", arr.Select(i => string.Format("{0}[]={1}", key, i)))); - } - else - { - var arr = (object[])val; - stringBuilder.Append(string.Join("&", arr.Select(i => string.Format("{0}[]={1}", key, JsonConvert.SerializeObject(i))))); - } - } - else - { - if (vtype == typeof(string)) - { - stringBuilder.AppendFormat("{0}={1}", key, val); - } - else - { - stringBuilder.AppendFormat("{0}={1}", key, JsonConvert.SerializeObject(val)); - } - } - } - stringBuilder.Append("&"); - } - } - }); - return new Uri(stringBuilder.ToString().TrimEnd('&')); - } - - protected T SendRequest(string resource, string method, object body, IDictionary parameters = null) - { - string statusCode = null; - string reason = null; - try - { - var request = (HttpWebRequest)WebRequest.Create(BuildRequestUrl(_baseUrl, resource, parameters)); - request.UseDefaultCredentials = true; - request.Method = method; - request.Proxy = null; - request.AutomaticDecompression = DecompressionMethods.GZip; - if (body != null) - { - request.Accept = "application/json"; - request.ContentType = "application/json"; - using (var streamWriter = new StreamWriter(request.GetRequestStream())) - { - streamWriter.Write(JsonConvert.SerializeObject(body)); - streamWriter.Flush(); - } - } - using (var response = (HttpWebResponse)request.GetResponse()) - { - statusCode = response.StatusCode.ToString(); - reason = response.StatusDescription; - if (response.StatusCode == HttpStatusCode.OK) - { - using (var stream = new StreamReader(response.GetResponseStream())) - { - string json = stream.ReadToEnd(); - return JsonConvert.DeserializeObject(json); - } - } - else - { - throw new Exception("Bad status code"); - } - } - } - catch (Exception ex) - { - var line = $"Resource request failed. [{method}] {resource}. Error code: {(statusCode ?? "Uncknown")}. Comment: {(reason ?? ex.Message)}"; - Log.Error(ex, line); - throw new InvalidOperationException(line, ex); - } - } - - protected T GET(string resource, IDictionary parameters = null) - { - return SendRequest(resource, "GET", null, parameters); - } - - protected T POST(string resource, object body, IDictionary parameters = null) - { - return SendRequest(resource, "POST", body, parameters); - } - - protected T DELETE(string resource, object body, IDictionary parameters = null) - { - return SendRequest(resource, "DELETE", body, parameters); - } - - static BaseProxy() - { - ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true; - ServicePointManager.Expect100Continue = false; - ServicePointManager.DefaultConnectionLimit = 8; - } - - public BaseProxy(string baseUri) - { - if (false == baseUri.EndsWith("/")) - _baseUrl = baseUri + "/"; - else - _baseUrl = baseUri; - } - } -} \ No newline at end of file diff --git a/ZeroLevel.Microservices/ExchangeTransportFactory.cs b/ZeroLevel.Microservices/ExchangeTransportFactory.cs deleted file mode 100644 index f46fd78..0000000 --- a/ZeroLevel.Microservices/ExchangeTransportFactory.cs +++ /dev/null @@ -1,109 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Reflection; -using ZeroLevel.Network.Microservices; -using ZeroLevel.Services.Network; -using ZeroLevel.Services.Network.Contract; - -namespace ZeroLevel.Microservices -{ - internal static class ExchangeTransportFactory - { - private static readonly Dictionary _customServers = new Dictionary(); - private static readonly Dictionary _customClients = new Dictionary(); - private static readonly ConcurrentDictionary _clientInstances = new ConcurrentDictionary(); - - /// - /// Scanning the specified assembly to find the types that implement the IExchangeServer or IExchangeClient interfaces - /// - internal static void ScanAndRegisterCustomTransport(Assembly asm) - { - foreach (var type in asm.GetExportedTypes()) - { - var serverAttr = type.GetCustomAttribute(); - if (serverAttr != null && - string.IsNullOrWhiteSpace(serverAttr.Protocol) == false && - typeof(IZObservableServer).IsAssignableFrom(type)) - { - _customServers[serverAttr.Protocol] = type; - } - var clientAttr = type.GetCustomAttribute(); - if (clientAttr != null && - string.IsNullOrWhiteSpace(clientAttr.Protocol) == false && - typeof(IZTransport).IsAssignableFrom(type)) - { - _customClients[clientAttr.Protocol] = type; - } - } - } - - /// - /// Creates a server to receive messages using the specified protocol - /// - /// Protocol - /// Server - internal static ExService GetServer(string protocol) - { - ExService instance = null; - if (protocol.Equals("socket", StringComparison.OrdinalIgnoreCase)) - { - instance = new ExService(new ZExSocketObservableServer(new System.Net.IPEndPoint(IPFinder.GetNonLoopbackAddress(), IPFinder.GetFreeTcpPort()))); - } - else - { - var key = protocol.Trim().ToLowerInvariant(); - if (_customServers.ContainsKey(key)) - { - instance = new ExService((IZObservableServer)Activator.CreateInstance(_customServers[key])); - } - } - if (instance != null) - { - return instance; - } - throw new NotSupportedException($"Protocol {protocol} not supported"); - } - - /// - /// Creates a client to access the server using the specified protocol - /// - /// Protocol - /// Server endpoint - /// Client - internal static ExClient GetClient(string protocol, string endpoint) - { - ExClient instance = null; - var cachee_key = $"{protocol}:{endpoint}"; - if (_clientInstances.ContainsKey(cachee_key)) - { - instance = _clientInstances[cachee_key]; - if (instance.Status == ZTransportStatus.Working) - { - return instance; - } - _clientInstances.TryRemove(cachee_key, out instance); - instance.Dispose(); - instance = null; - } - if (protocol.Equals("socket", StringComparison.OrdinalIgnoreCase)) - { - instance = new ExClient(new ZSocketClient(SocketExtensions.CreateIPEndPoint(endpoint))); - } - else - { - var key = protocol.Trim().ToLowerInvariant(); - if (_customClients.ContainsKey(key)) - { - instance = new ExClient((IZTransport)Activator.CreateInstance(_customClients[key], new object[] { endpoint })); - } - } - if (instance != null) - { - _clientInstances[cachee_key] = instance; - return instance; - } - throw new NotSupportedException($"Protocol {protocol} not supported"); - } - } -} \ No newline at end of file diff --git a/ZeroLevel.Microservices/Properties/AssemblyInfo.cs b/ZeroLevel.Microservices/Properties/AssemblyInfo.cs deleted file mode 100644 index 916d4b4..0000000 --- a/ZeroLevel.Microservices/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("ZeroLevel.Microservices")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("ZeroLevel.Microservices")] -[assembly: AssemblyCopyright("Copyright © 2019")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("6452d91a-2dac-4982-83af-77472051e81b")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/ZeroLevel.Microservices/ZeroLevel.Microservices.csproj b/ZeroLevel.Microservices/ZeroLevel.Microservices.csproj deleted file mode 100644 index 5df2e61..0000000 --- a/ZeroLevel.Microservices/ZeroLevel.Microservices.csproj +++ /dev/null @@ -1,71 +0,0 @@ - - - - - Debug - AnyCPU - {6452D91A-2DAC-4982-83AF-77472051E81B} - Library - Properties - ZeroLevel.Microservices - ZeroLevel.Microservices - v4.7.2 - 512 - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - ..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - {37020d8d-34e8-4ec3-a447-8396d5080457} - ZeroLevel - - - - - - - \ No newline at end of file diff --git a/ZeroLevel.Microservices/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs b/ZeroLevel.Microservices/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs deleted file mode 100644 index e69de29..0000000 diff --git a/ZeroLevel.Microservices/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs b/ZeroLevel.Microservices/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs deleted file mode 100644 index e69de29..0000000 diff --git a/ZeroLevel.Microservices/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs b/ZeroLevel.Microservices/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs deleted file mode 100644 index e69de29..0000000 diff --git a/ZeroLevel.Microservices/obj/Debug/ZeroLevel.Microservices.csproj.CoreCompileInputs.cache b/ZeroLevel.Microservices/obj/Debug/ZeroLevel.Microservices.csproj.CoreCompileInputs.cache deleted file mode 100644 index 104314d..0000000 --- a/ZeroLevel.Microservices/obj/Debug/ZeroLevel.Microservices.csproj.CoreCompileInputs.cache +++ /dev/null @@ -1 +0,0 @@ -48781ba1f58e845d50aedda0cbff5881dfe0563f diff --git a/ZeroLevel.Microservices/obj/Debug/ZeroLevel.Microservices.csprojAssemblyReference.cache b/ZeroLevel.Microservices/obj/Debug/ZeroLevel.Microservices.csprojAssemblyReference.cache deleted file mode 100644 index 581de84..0000000 Binary files a/ZeroLevel.Microservices/obj/Debug/ZeroLevel.Microservices.csprojAssemblyReference.cache and /dev/null differ diff --git a/ZeroLevel.Microservices/packages.config b/ZeroLevel.Microservices/packages.config deleted file mode 100644 index 97c22dc..0000000 --- a/ZeroLevel.Microservices/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/ZeroLevel.sln b/ZeroLevel.sln index aef504b..444fdaa 100644 --- a/ZeroLevel.sln +++ b/ZeroLevel.sln @@ -5,8 +5,6 @@ VisualStudioVersion = 15.0.28307.421 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZeroLevel", "ZeroLevel\ZeroLevel.csproj", "{37020D8D-34E8-4EC3-A447-8396D5080457}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZeroLevel.Microservices", "ZeroLevel.Microservices\ZeroLevel.Microservices.csproj", "{6452D91A-2DAC-4982-83AF-77472051E81B}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZeroLevel.Discovery", "ZeroLevel.Discovery\ZeroLevel.Discovery.csproj", "{4F55B23F-938C-4DA2-B6DC-B6BC66D36073}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZeroExample", "ZeroExample\ZeroExample.csproj", "{50CEBEC2-2571-4592-AFD2-970BDB41947B}" @@ -33,18 +31,6 @@ Global {37020D8D-34E8-4EC3-A447-8396D5080457}.Release|x64.Build.0 = Release|Any CPU {37020D8D-34E8-4EC3-A447-8396D5080457}.Release|x86.ActiveCfg = Release|Any CPU {37020D8D-34E8-4EC3-A447-8396D5080457}.Release|x86.Build.0 = Release|Any CPU - {6452D91A-2DAC-4982-83AF-77472051E81B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6452D91A-2DAC-4982-83AF-77472051E81B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6452D91A-2DAC-4982-83AF-77472051E81B}.Debug|x64.ActiveCfg = Debug|Any CPU - {6452D91A-2DAC-4982-83AF-77472051E81B}.Debug|x64.Build.0 = Debug|Any CPU - {6452D91A-2DAC-4982-83AF-77472051E81B}.Debug|x86.ActiveCfg = Debug|Any CPU - {6452D91A-2DAC-4982-83AF-77472051E81B}.Debug|x86.Build.0 = Debug|Any CPU - {6452D91A-2DAC-4982-83AF-77472051E81B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6452D91A-2DAC-4982-83AF-77472051E81B}.Release|Any CPU.Build.0 = Release|Any CPU - {6452D91A-2DAC-4982-83AF-77472051E81B}.Release|x64.ActiveCfg = Release|Any CPU - {6452D91A-2DAC-4982-83AF-77472051E81B}.Release|x64.Build.0 = Release|Any CPU - {6452D91A-2DAC-4982-83AF-77472051E81B}.Release|x86.ActiveCfg = Release|Any CPU - {6452D91A-2DAC-4982-83AF-77472051E81B}.Release|x86.Build.0 = Release|Any CPU {4F55B23F-938C-4DA2-B6DC-B6BC66D36073}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4F55B23F-938C-4DA2-B6DC-B6BC66D36073}.Debug|Any CPU.Build.0 = Debug|Any CPU {4F55B23F-938C-4DA2-B6DC-B6BC66D36073}.Debug|x64.ActiveCfg = Debug|Any CPU diff --git a/ZeroLevel/Services/Network/Contract/IExClient.cs b/ZeroLevel/Services/Network/Contract/IExClient.cs index d267db6..a4f7193 100644 --- a/ZeroLevel/Services/Network/Contract/IExClient.cs +++ b/ZeroLevel/Services/Network/Contract/IExClient.cs @@ -5,9 +5,14 @@ using ZeroLevel.Models; namespace ZeroLevel.Services.Network { public interface IExClient + : IDisposable { event Action Connected; + void ForceConnect(); + + ZTransportStatus Status { get; } + IPEndPoint Endpoint { get; } InvokeResult Send(T obj); diff --git a/ZeroLevel.Discovery/ExchangeTransportFactory.cs b/ZeroLevel/Services/Network/ExchangeTransportFactory.cs similarity index 81% rename from ZeroLevel.Discovery/ExchangeTransportFactory.cs rename to ZeroLevel/Services/Network/ExchangeTransportFactory.cs index f46fd78..48c0806 100644 --- a/ZeroLevel.Discovery/ExchangeTransportFactory.cs +++ b/ZeroLevel/Services/Network/ExchangeTransportFactory.cs @@ -6,13 +6,13 @@ using ZeroLevel.Network.Microservices; using ZeroLevel.Services.Network; using ZeroLevel.Services.Network.Contract; -namespace ZeroLevel.Microservices +namespace ZeroLevel.Network { - internal static class ExchangeTransportFactory + public static class ExchangeTransportFactory { private static readonly Dictionary _customServers = new Dictionary(); private static readonly Dictionary _customClients = new Dictionary(); - private static readonly ConcurrentDictionary _clientInstances = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary _clientInstances = new ConcurrentDictionary(); /// /// Scanning the specified assembly to find the types that implement the IExchangeServer or IExchangeClient interfaces @@ -43,12 +43,12 @@ namespace ZeroLevel.Microservices /// /// Protocol /// Server - internal static ExService GetServer(string protocol) + public static IExService GetServer(string protocol, int port = -1) { ExService instance = null; if (protocol.Equals("socket", StringComparison.OrdinalIgnoreCase)) { - instance = new ExService(new ZExSocketObservableServer(new System.Net.IPEndPoint(IPFinder.GetNonLoopbackAddress(), IPFinder.GetFreeTcpPort()))); + instance = new ExService(new ZExSocketObservableServer(new System.Net.IPEndPoint(NetUtils.GetNonLoopbackAddress(), port == -1 ? NetUtils.GetFreeTcpPort() : port))); } else { @@ -64,16 +64,15 @@ namespace ZeroLevel.Microservices } throw new NotSupportedException($"Protocol {protocol} not supported"); } - /// /// Creates a client to access the server using the specified protocol /// /// Protocol /// Server endpoint /// Client - internal static ExClient GetClient(string protocol, string endpoint) + public static IExClient GetClientWithCache(string protocol, string endpoint) { - ExClient instance = null; + IExClient instance = null; var cachee_key = $"{protocol}:{endpoint}"; if (_clientInstances.ContainsKey(cachee_key)) { @@ -86,9 +85,17 @@ namespace ZeroLevel.Microservices instance.Dispose(); instance = null; } + instance = GetClient(protocol, endpoint); + _clientInstances[cachee_key] = instance; + return instance; + } + + public static IExClient GetClient(string protocol, string endpoint) + { + ExClient instance = null; if (protocol.Equals("socket", StringComparison.OrdinalIgnoreCase)) { - instance = new ExClient(new ZSocketClient(SocketExtensions.CreateIPEndPoint(endpoint))); + instance = new ExClient(new ZSocketClient(NetUtils.CreateIPEndPoint(endpoint))); } else { @@ -100,7 +107,6 @@ namespace ZeroLevel.Microservices } if (instance != null) { - _clientInstances[cachee_key] = instance; return instance; } throw new NotSupportedException($"Protocol {protocol} not supported"); diff --git a/ZeroLevel.Microservices/Model/Checkpoint.cs b/ZeroLevel/Services/Network/Microservices/Checkpoint.cs similarity index 98% rename from ZeroLevel.Microservices/Model/Checkpoint.cs rename to ZeroLevel/Services/Network/Microservices/Checkpoint.cs index 05d7401..7d313b1 100644 --- a/ZeroLevel.Microservices/Model/Checkpoint.cs +++ b/ZeroLevel/Services/Network/Microservices/Checkpoint.cs @@ -2,7 +2,7 @@ using System.Runtime.Serialization; using ZeroLevel.Services.Serialization; -namespace ZeroLevel.Microservices.Model +namespace ZeroLevel.Network.Microservices { [DataContract] public class Checkpoint : diff --git a/ZeroLevel.Microservices/Model/CheckpointArc.cs b/ZeroLevel/Services/Network/Microservices/CheckpointArc.cs similarity index 93% rename from ZeroLevel.Microservices/Model/CheckpointArc.cs rename to ZeroLevel/Services/Network/Microservices/CheckpointArc.cs index fad92bc..8d0d59d 100644 --- a/ZeroLevel.Microservices/Model/CheckpointArc.cs +++ b/ZeroLevel/Services/Network/Microservices/CheckpointArc.cs @@ -1,6 +1,6 @@ using System.Runtime.Serialization; -namespace ZeroLevel.Microservices.Model +namespace ZeroLevel.Network.Microservices { [DataContract] public sealed class CheckpointArc diff --git a/ZeroLevel.Microservices/Model/CheckpointType.cs b/ZeroLevel/Services/Network/Microservices/CheckpointType.cs similarity index 73% rename from ZeroLevel.Microservices/Model/CheckpointType.cs rename to ZeroLevel/Services/Network/Microservices/CheckpointType.cs index 1f360f4..352b702 100644 --- a/ZeroLevel.Microservices/Model/CheckpointType.cs +++ b/ZeroLevel/Services/Network/Microservices/CheckpointType.cs @@ -1,4 +1,4 @@ -namespace ZeroLevel.Microservices.Model +namespace ZeroLevel.Network.Microservices { public enum CheckpointType { diff --git a/ZeroLevel.Microservices/WebApiDiscoveryClient.cs b/ZeroLevel/Services/Network/Microservices/DiscoveryClient.cs similarity index 54% rename from ZeroLevel.Microservices/WebApiDiscoveryClient.cs rename to ZeroLevel/Services/Network/Microservices/DiscoveryClient.cs index 5c5f440..8b52894 100644 --- a/ZeroLevel.Microservices/WebApiDiscoveryClient.cs +++ b/ZeroLevel/Services/Network/Microservices/DiscoveryClient.cs @@ -3,31 +3,16 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading; -using ZeroLevel.Microservices.Contracts; using ZeroLevel.Models; +using ZeroLevel.Network; using ZeroLevel.Network.Microservices; -using ZeroLevel.ProxyREST; using ZeroLevel.Services.Collections; -namespace ZeroLevel.Microservices +namespace ZeroLevel.Services.Network.Microservices { - public sealed class WebApiDiscoveryClient : - BaseProxy, IDiscoveryClient + public class DiscoveryClient + : IDiscoveryClient { - #region WebAPI - - private IEnumerable GetRecords() - { - return GET>("api/v0/routes"); - } - - public InvokeResult Post(MicroserviceInfo info) - { - return POST("api/v0/routes", info); - } - - #endregion WebAPI - private readonly ConcurrentDictionary> _tableByKey = new ConcurrentDictionary>(); @@ -38,10 +23,11 @@ namespace ZeroLevel.Microservices new ConcurrentDictionary>(); private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); + private readonly IExClient _discoveryServerClient; - public WebApiDiscoveryClient(string url) - : base(url) + public DiscoveryClient(string protocol, string endpoint) { + _discoveryServerClient = ExchangeTransportFactory.GetClient(protocol, endpoint); UpdateServiceListInfo(); Sheduller.RemindEvery(TimeSpan.FromSeconds(30), UpdateServiceListInfo); } @@ -79,63 +65,89 @@ namespace ZeroLevel.Microservices private void UpdateServiceListInfo() { - IEnumerable records; - try - { - records = GetRecords(); - } - catch (Exception ex) - { - Log.Error(ex, "[WebApiDiscoveryClient] Update service list error, discrovery service response is absent"); - return; - } - if (records == null) - { - Log.Warning("[WebApiDiscoveryClient] Update service list canceled, discrovery response is empty"); - return; - } - _lock.EnterWriteLock(); - try + _discoveryServerClient.ForceConnect(); + if (_discoveryServerClient.Status == ZTransportStatus.Working) { - _tableByGroups.Clear(); - _tableByTypes.Clear(); - var keysToRemove = new List(_tableByKey.Keys); - foreach (var info in records) + IEnumerable records = null; + try { - var key = info.ServiceKey.Trim().ToLowerInvariant(); - UpdateOrAddRecord(key, info); - keysToRemove.Remove(key); + var ir = _discoveryServerClient.Request>("services", response => records = response); + if (!ir.Success) + { + Log.Warning($"[DiscoveryClient] UpdateServiceListInfo. Error request to inbox 'services'. {ir.Comment}"); + return; + } } - RoundRobinCollection removed; - foreach (var key in keysToRemove) + catch (Exception ex) { - _tableByKey.TryRemove(key, out removed); - removed.Dispose(); + Log.Error(ex, "[DiscoveryClient] UpdateServiceListInfo. Discrovery service response is absent"); + return; + } + if (records == null) + { + Log.Warning("[DiscoveryClient] UpdateServiceListInfo. Discrovery response is empty"); + return; + } + _lock.EnterWriteLock(); + try + { + _tableByGroups.Clear(); + _tableByTypes.Clear(); + var keysToRemove = new List(_tableByKey.Keys); + foreach (var info in records) + { + var key = info.ServiceKey.Trim().ToLowerInvariant(); + UpdateOrAddRecord(key, info); + keysToRemove.Remove(key); + } + foreach (var key in keysToRemove) + { + _tableByKey.TryRemove(key, out RoundRobinCollection removed); + removed.Dispose(); + } + } + catch (Exception ex) + { + Log.Error(ex, "[DiscoveryClient] UpdateServiceListInfo. Update local routing table error."); + } + finally + { + _lock.ExitWriteLock(); } } - catch (Exception ex) - { - Log.Error(ex, "[WebApiDiscoveryClient] Update service list error"); - } - finally + else { - _lock.ExitWriteLock(); + Log.Warning("[DiscoveryClient] UpdateServiceListInfo. No connection to discovery server"); } } - public void Register(MicroserviceInfo info) + public bool Register(MicroserviceInfo info) { - try + _discoveryServerClient.ForceConnect(); + if (_discoveryServerClient.Status == ZTransportStatus.Working) { - var result = Post(info); - if (result.Success == false) + bool result = false; + try { - Log.Warning($"[WebApiDiscoveryClient] Service can't register. Discovery reason: {result.Comment}. Comment: {result.Comment}"); + _discoveryServerClient.Request("register", info, r => + { + result = r.Success; + if (!result) + { + Log.Warning($"[DiscoveryClient] Register canceled. Discovery reason: {r.Comment}. Comment: {r.Comment}"); + } + }); } + catch (Exception ex) + { + Log.Error(ex, "[DiscoveryClient] Register fault"); + } + return result; } - catch (Exception ex) + else { - Log.Error(ex, "[WebApiDiscoveryClient] Fault register"); + Log.Warning("[DiscoveryClient] Register. No connection to discovery server"); + return false; } } diff --git a/ZeroLevel.Microservices/ExServiceHost.cs b/ZeroLevel/Services/Network/Microservices/ExServiceHost.cs similarity index 98% rename from ZeroLevel.Microservices/ExServiceHost.cs rename to ZeroLevel/Services/Network/Microservices/ExServiceHost.cs index fa8d5b6..7f631e7 100644 --- a/ZeroLevel.Microservices/ExServiceHost.cs +++ b/ZeroLevel/Services/Network/Microservices/ExServiceHost.cs @@ -4,19 +4,19 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; -using ZeroLevel.Microservices.Contracts; +using ZeroLevel.Network; using ZeroLevel.Network.Microservices; using ZeroLevel.Services.Network; namespace ZeroLevel.Microservices { - internal sealed class ExServiceHost + public sealed class ExServiceHost : IDisposable { private class MetaService { public MicroserviceInfo ServiceInfo { get; set; } - public ExService Server { get; set; } + public IExService Server { get; set; } } private bool _disposed = false; @@ -26,13 +26,13 @@ namespace ZeroLevel.Microservices private readonly ConcurrentDictionary _services = new ConcurrentDictionary(); - internal ExServiceHost(IDiscoveryClient client) + public ExServiceHost(IDiscoveryClient client) { _discoveryClient = client; _registerTaskKey = Sheduller.RemindEvery(TimeSpan.FromMilliseconds(50), TimeSpan.FromSeconds(15), RegisterServicesInDiscovery); } - internal IExService RegisterService(IExchangeService service) + public IExService RegisterService(IExchangeService service) { try { @@ -76,7 +76,7 @@ namespace ZeroLevel.Microservices } } - internal IExService RegisterService(MicroserviceInfo serviceInfo) + public IExService RegisterService(MicroserviceInfo serviceInfo) { try { diff --git a/ZeroLevel.Microservices/Exchange.cs b/ZeroLevel/Services/Network/Microservices/Exchange.cs similarity index 99% rename from ZeroLevel.Microservices/Exchange.cs rename to ZeroLevel/Services/Network/Microservices/Exchange.cs index 5b4d4e7..d61d83d 100644 --- a/ZeroLevel.Microservices/Exchange.cs +++ b/ZeroLevel/Services/Network/Microservices/Exchange.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; -using ZeroLevel.Microservices.Contracts; +using ZeroLevel.Network; using ZeroLevel.Network.Microservices; using ZeroLevel.Services.Network; diff --git a/ZeroLevel.Microservices/Contracts/IDiscoveryClient.cs b/ZeroLevel/Services/Network/Microservices/IDiscoveryClient.cs similarity index 83% rename from ZeroLevel.Microservices/Contracts/IDiscoveryClient.cs rename to ZeroLevel/Services/Network/Microservices/IDiscoveryClient.cs index 6bd1b3f..482dfd8 100644 --- a/ZeroLevel.Microservices/Contracts/IDiscoveryClient.cs +++ b/ZeroLevel/Services/Network/Microservices/IDiscoveryClient.cs @@ -1,11 +1,11 @@ using System.Collections.Generic; using ZeroLevel.Network.Microservices; -namespace ZeroLevel.Microservices.Contracts +namespace ZeroLevel.Network { public interface IDiscoveryClient { - void Register(MicroserviceInfo info); + bool Register(MicroserviceInfo info); IEnumerable GetServiceEndpoints(string serviceKey); diff --git a/ZeroLevel.Microservices/Contracts/IExchangeService.cs b/ZeroLevel/Services/Network/Microservices/IExchangeService.cs similarity index 84% rename from ZeroLevel.Microservices/Contracts/IExchangeService.cs rename to ZeroLevel/Services/Network/Microservices/IExchangeService.cs index 67c4823..f54650c 100644 --- a/ZeroLevel.Microservices/Contracts/IExchangeService.cs +++ b/ZeroLevel/Services/Network/Microservices/IExchangeService.cs @@ -1,4 +1,4 @@ -namespace ZeroLevel.Microservices.Contracts +namespace ZeroLevel.Network { public interface IExchangeService { diff --git a/ZeroLevel/Services/Network/Models/MicroserviceInfo.cs b/ZeroLevel/Services/Network/Models/MicroserviceInfo.cs index c89c40b..3ad94fc 100644 --- a/ZeroLevel/Services/Network/Models/MicroserviceInfo.cs +++ b/ZeroLevel/Services/Network/Models/MicroserviceInfo.cs @@ -1,12 +1,13 @@ using System; using System.Runtime.Serialization; +using ZeroLevel.Services.Serialization; namespace ZeroLevel.Network.Microservices { [Serializable] [DataContract] public sealed class MicroserviceInfo : - IEquatable + IEquatable, IBinarySerializable { public const string DEFAULT_GROUP_NAME = "__service_default_group__"; public const string DEFAULT_TYPE_NAME = "__service_default_type__"; @@ -73,6 +74,26 @@ namespace ZeroLevel.Network.Microservices return this.ServiceKey.GetHashCode() ^ this.Protocol.GetHashCode() ^ this.Endpoint.GetHashCode(); } + public void Serialize(IBinaryWriter writer) + { + writer.WriteString(this.ServiceKey); + writer.WriteString(this.ServiceGroup); + writer.WriteString(this.ServiceType); + writer.WriteString(this.Protocol); + writer.WriteString(this.Endpoint); + writer.WriteString(this.Version); + } + + public void Deserialize(IBinaryReader reader) + { + this.ServiceKey = reader.ReadString(); + this.ServiceGroup = reader.ReadString(); + this.ServiceType = reader.ReadString(); + this.Protocol = reader.ReadString(); + this.Endpoint = reader.ReadString(); + this.Version = reader.ReadString(); + } + public override string ToString() { return $"{ServiceKey} ({Version})"; diff --git a/ZeroLevel/Services/Network/Services/IPFinder.cs b/ZeroLevel/Services/Network/NetUtils.cs similarity index 53% rename from ZeroLevel/Services/Network/Services/IPFinder.cs rename to ZeroLevel/Services/Network/NetUtils.cs index e3c4be6..d554b82 100644 --- a/ZeroLevel/Services/Network/Services/IPFinder.cs +++ b/ZeroLevel/Services/Network/NetUtils.cs @@ -1,12 +1,48 @@ using System; +using System.Globalization; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; namespace ZeroLevel.Services.Network { - public static class IPFinder + public static class NetUtils { + public static int Compare(this IPEndPoint x, IPEndPoint y) + { + var xx = x.Address.ToString(); + var yy = y.Address.ToString(); + var result = string.CompareOrdinal(xx, yy); + return result == 0 ? x.Port.CompareTo(y.Port) : result; + } + + public static IPEndPoint CreateIPEndPoint(string endPoint) + { + string[] ep = endPoint.Split(':'); + if (ep.Length < 2) throw new FormatException("Invalid endpoint format"); + IPAddress ip; + if (ep.Length > 2) + { + if (!IPAddress.TryParse(string.Join(":", ep, 0, ep.Length - 1), out ip)) + { + throw new FormatException("Invalid ip-adress"); + } + } + else + { + if (!IPAddress.TryParse(ep[0], out ip)) + { + throw new FormatException("Invalid ip-adress"); + } + } + int port; + if (!int.TryParse(ep[ep.Length - 1], NumberStyles.None, NumberFormatInfo.CurrentInfo, out port)) + { + throw new FormatException("Invalid port"); + } + return new IPEndPoint(ip, port); + } + public static int GetFreeTcpPort() { TcpListener l = new TcpListener(IPAddress.Loopback, 0); diff --git a/ZeroLevel/Services/Network/Services/ExClient.cs b/ZeroLevel/Services/Network/Services/ExClient.cs index ca61457..713af59 100644 --- a/ZeroLevel/Services/Network/Services/ExClient.cs +++ b/ZeroLevel/Services/Network/Services/ExClient.cs @@ -6,8 +6,8 @@ using ZeroLevel.Services.Network.Services; namespace ZeroLevel.Services.Network { - public class ExClient - : ZBaseNetwork, IExClient, IZBackward, IDisposable + internal sealed class ExClient + : ZBaseNetwork, IExClient, IZBackward { private readonly IZTransport _transport; private readonly ExRouter _router; diff --git a/ZeroLevel/Services/Network/Services/ExService.cs b/ZeroLevel/Services/Network/Services/ExService.cs index d9a9857..b6bf69a 100644 --- a/ZeroLevel/Services/Network/Services/ExService.cs +++ b/ZeroLevel/Services/Network/Services/ExService.cs @@ -5,7 +5,7 @@ using ZeroLevel.Services.Network.Services; namespace ZeroLevel.Services.Network { - public class ExService + internal sealed class ExService : ZBaseNetwork, IExService { private readonly ExRouter _router; diff --git a/ZeroLevel/Services/Network/Services/ZExSocketObservableServer.cs b/ZeroLevel/Services/Network/Services/ZExSocketObservableServer.cs index 92d7fe2..11a2420 100644 --- a/ZeroLevel/Services/Network/Services/ZExSocketObservableServer.cs +++ b/ZeroLevel/Services/Network/Services/ZExSocketObservableServer.cs @@ -14,9 +14,9 @@ namespace ZeroLevel.Services.Network public IPEndPoint Endpoint => base.LocalEndpoint; - public event Action OnMessage = (f, c) => { }; + public event Action OnMessage = (_, __) => { }; - public event Func OnRequest = (f, c) => null; + public event Func OnRequest = (_, __) => null; protected override void Handle(Frame frame, IZBackward client) { diff --git a/ZeroLevel/Services/Network/SocketExtensions.cs b/ZeroLevel/Services/Network/SocketExtensions.cs deleted file mode 100644 index 306aaaa..0000000 --- a/ZeroLevel/Services/Network/SocketExtensions.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.Globalization; -using System.Net; - -namespace ZeroLevel.Services.Network -{ - public static class SocketExtensions - { - public static int Compare(this IPEndPoint x, IPEndPoint y) - { - var xx = x.Address.ToString(); - var yy = y.Address.ToString(); - var result = string.CompareOrdinal(xx, yy); - return result == 0 ? x.Port.CompareTo(y.Port) : result; - } - - public static IPEndPoint CreateIPEndPoint(string endPoint) - { - string[] ep = endPoint.Split(':'); - if (ep.Length < 2) throw new FormatException("Invalid endpoint format"); - IPAddress ip; - if (ep.Length > 2) - { - if (!IPAddress.TryParse(string.Join(":", ep, 0, ep.Length - 1), out ip)) - { - throw new FormatException("Invalid ip-adress"); - } - } - else - { - if (!IPAddress.TryParse(ep[0], out ip)) - { - throw new FormatException("Invalid ip-adress"); - } - } - int port; - if (!int.TryParse(ep[ep.Length - 1], NumberStyles.None, NumberFormatInfo.CurrentInfo, out port)) - { - throw new FormatException("Invalid port"); - } - return new IPEndPoint(ip, port); - } - } -} \ No newline at end of file diff --git a/ZeroLevel/ZeroLevel.csproj b/ZeroLevel/ZeroLevel.csproj index db88542..c1ee42e 100644 --- a/ZeroLevel/ZeroLevel.csproj +++ b/ZeroLevel/ZeroLevel.csproj @@ -238,6 +238,15 @@ + + + + + + + + + @@ -251,11 +260,10 @@ - + - diff --git a/ZeroLevel/obj/Debug/ZeroLevel.csproj.CoreCompileInputs.cache b/ZeroLevel/obj/Debug/ZeroLevel.csproj.CoreCompileInputs.cache index e77e86a..5d7709e 100644 --- a/ZeroLevel/obj/Debug/ZeroLevel.csproj.CoreCompileInputs.cache +++ b/ZeroLevel/obj/Debug/ZeroLevel.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -7dc74ae62ea3925694bcfe614d7c1f201cc0d873 +34e7ecccf08c9607e57fb18cb5dd41e7bc1a3610 diff --git a/ZeroLevel/obj/Debug/ZeroLevel.csprojAssemblyReference.cache b/ZeroLevel/obj/Debug/ZeroLevel.csprojAssemblyReference.cache index 55850f9..a0c6a03 100644 Binary files a/ZeroLevel/obj/Debug/ZeroLevel.csprojAssemblyReference.cache and b/ZeroLevel/obj/Debug/ZeroLevel.csprojAssemblyReference.cache differ