Browse Source

Add Nodediscovry

master
Savorboard 5 years ago
parent
commit
59f90b07bb
8 changed files with 306 additions and 0 deletions
  1. +38
    -0
      src/DotNetCore.CAP.Dashboard/NodeDiscovery/CAP.DiscoveryOptions.cs
  2. +56
    -0
      src/DotNetCore.CAP.Dashboard/NodeDiscovery/CAP.DiscoveryOptionsExtensions.cs
  3. +28
    -0
      src/DotNetCore.CAP.Dashboard/NodeDiscovery/IDiscoveryProviderFactory.Default.cs
  4. +10
    -0
      src/DotNetCore.CAP.Dashboard/NodeDiscovery/IDiscoveryProviderFactory.cs
  5. +106
    -0
      src/DotNetCore.CAP.Dashboard/NodeDiscovery/INodeDiscoveryProvider.Consul.cs
  6. +15
    -0
      src/DotNetCore.CAP.Dashboard/NodeDiscovery/INodeDiscoveryProvider.cs
  7. +35
    -0
      src/DotNetCore.CAP.Dashboard/NodeDiscovery/IProcessingServer.Consul.cs
  8. +18
    -0
      src/DotNetCore.CAP.Dashboard/NodeDiscovery/Node.cs

+ 38
- 0
src/DotNetCore.CAP.Dashboard/NodeDiscovery/CAP.DiscoveryOptions.cs View File

@@ -0,0 +1,38 @@
// Copyright (c) .NET Core Community. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

namespace DotNetCore.CAP.Dashboard.NodeDiscovery
{
public class DiscoveryOptions
{
public const string DefaultDiscoveryServerHost = "localhost";
public const int DefaultDiscoveryServerPort = 8500;

public const string DefaultCurrentNodeHostName = "localhost";
public const int DefaultCurrentNodePort = 5000;

public const string DefaultMatchPath = "/cap";

public DiscoveryOptions()
{
DiscoveryServerHostName = DefaultDiscoveryServerHost;
DiscoveryServerPort = DefaultDiscoveryServerPort;

CurrentNodeHostName = DefaultCurrentNodeHostName;
CurrentNodePort = DefaultCurrentNodePort;

MatchPath = DefaultMatchPath;
}

public string DiscoveryServerHostName { get; set; }
public int DiscoveryServerPort { get; set; }

public string CurrentNodeHostName { get; set; }
public int CurrentNodePort { get; set; }

public string NodeId { get; set; }
public string NodeName { get; set; }

public string MatchPath { get; set; }
}
}

+ 56
- 0
src/DotNetCore.CAP.Dashboard/NodeDiscovery/CAP.DiscoveryOptionsExtensions.cs View File

@@ -0,0 +1,56 @@
// Copyright (c) .NET Core Community. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System;
using DotNetCore.CAP;
using Microsoft.Extensions.DependencyInjection;

namespace DotNetCore.CAP.Dashboard.NodeDiscovery
{
internal sealed class DiscoveryOptionsExtension : ICapOptionsExtension
{
private readonly Action<DiscoveryOptions> _options;

public DiscoveryOptionsExtension(Action<DiscoveryOptions> option)
{
_options = option;
}

public void AddServices(IServiceCollection services)
{
var discoveryOptions = new DiscoveryOptions();

_options?.Invoke(discoveryOptions);
services.AddSingleton(discoveryOptions);

services.AddSingleton<IDiscoveryProviderFactory, DiscoveryProviderFactory>();
services.AddSingleton<IProcessingServer, ConsulProcessingNodeServer>();
services.AddSingleton(x =>
{
var configOptions = x.GetService<DiscoveryOptions>();
var factory = x.GetService<IDiscoveryProviderFactory>();
return factory.Create(configOptions);
});
}
}

public static class CapDiscoveryOptionsExtensions
{
public static CapOptions UseDiscovery(this CapOptions capOptions)
{
return capOptions.UseDiscovery(opt => { });
}

public static CapOptions UseDiscovery(this CapOptions capOptions, Action<DiscoveryOptions> options)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}

capOptions.RegisterExtension(new DiscoveryOptionsExtension(options));

return capOptions;
}
}
}

+ 28
- 0
src/DotNetCore.CAP.Dashboard/NodeDiscovery/IDiscoveryProviderFactory.Default.cs View File

@@ -0,0 +1,28 @@
// Copyright (c) .NET Core Community. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System;
using Microsoft.Extensions.Logging;

namespace DotNetCore.CAP.Dashboard.NodeDiscovery
{
internal class DiscoveryProviderFactory : IDiscoveryProviderFactory
{
private readonly ILoggerFactory _loggerFactory;

public DiscoveryProviderFactory(ILoggerFactory loggerFactory)
{
_loggerFactory = loggerFactory;
}

public INodeDiscoveryProvider Create(DiscoveryOptions options)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}

return new ConsulNodeDiscoveryProvider(_loggerFactory, options);
}
}
}

+ 10
- 0
src/DotNetCore.CAP.Dashboard/NodeDiscovery/IDiscoveryProviderFactory.cs View File

@@ -0,0 +1,10 @@
// Copyright (c) .NET Core Community. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

namespace DotNetCore.CAP.Dashboard.NodeDiscovery
{
internal interface IDiscoveryProviderFactory
{
INodeDiscoveryProvider Create(DiscoveryOptions options);
}
}

+ 106
- 0
src/DotNetCore.CAP.Dashboard/NodeDiscovery/INodeDiscoveryProvider.Consul.cs View File

@@ -0,0 +1,106 @@
// Copyright (c) .NET Core Community. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Consul;
using Microsoft.Extensions.Logging;

namespace DotNetCore.CAP.Dashboard.NodeDiscovery
{
public class ConsulNodeDiscoveryProvider : INodeDiscoveryProvider, IDisposable
{
private readonly ILogger<ConsulNodeDiscoveryProvider> _logger;
private readonly DiscoveryOptions _options;
private ConsulClient _consul;

public ConsulNodeDiscoveryProvider(ILoggerFactory logger, DiscoveryOptions options)
{
_logger = logger.CreateLogger<ConsulNodeDiscoveryProvider>();
_options = options;

InitClient();
}

public void Dispose()
{
_consul.Dispose();
}

public async Task<IList<Node>> GetNodes()
{
try
{
var nodes = new List<Node>();
var services = await _consul.Catalog.Services();
foreach (var service in services.Response)
{
var serviceInfo = await _consul.Catalog.Service(service.Key);
var node = serviceInfo.Response.SkipWhile(x => !x.ServiceTags.Contains("CAP"))
.Select(info => new Node
{
Id = info.ServiceID,
Name = info.ServiceName,
Address = info.ServiceAddress,
Port = info.ServicePort,
Tags = string.Join(", ", info.ServiceTags)
}).ToList();

nodes.AddRange(node);
}

CapCache.Global.AddOrUpdate("cap.nodes.count", nodes.Count, TimeSpan.FromSeconds(60), true);

return nodes;
}
catch (Exception ex)
{
CapCache.Global.AddOrUpdate("cap.nodes.count", 0, TimeSpan.FromSeconds(20));

_logger.LogError(
$"Get consul nodes raised an exception. Exception:{ex.Message},{ex.InnerException.Message}");
return null;
}
}

public Task RegisterNode()
{
try
{
return _consul.Agent.ServiceRegister(new AgentServiceRegistration
{
ID = _options.NodeId,
Name = _options.NodeName,
Address = _options.CurrentNodeHostName,
Port = _options.CurrentNodePort,
Tags = new[] {"CAP", "Client", "Dashboard"},
Check = new AgentServiceCheck
{
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(30),
Interval = TimeSpan.FromSeconds(10),
Status = HealthStatus.Passing,
HTTP =
$"http://{_options.CurrentNodeHostName}:{_options.CurrentNodePort}{_options.MatchPath}/health"
}
});
}
catch (Exception ex)
{
_logger.LogError(
$"Get consul nodes raised an exception. Exception:{ex.Message},{ex.InnerException.Message}");
return null;
}
}

private void InitClient()
{
_consul = new ConsulClient(config =>
{
config.WaitTime = TimeSpan.FromSeconds(5);
config.Address = new Uri($"http://{_options.DiscoveryServerHostName}:{_options.DiscoveryServerPort}");
});
}
}
}

+ 15
- 0
src/DotNetCore.CAP.Dashboard/NodeDiscovery/INodeDiscoveryProvider.cs View File

@@ -0,0 +1,15 @@
// Copyright (c) .NET Core Community. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System.Collections.Generic;
using System.Threading.Tasks;

namespace DotNetCore.CAP.Dashboard.NodeDiscovery
{
public interface INodeDiscoveryProvider
{
Task<IList<Node>> GetNodes();

Task RegisterNode();
}
}

+ 35
- 0
src/DotNetCore.CAP.Dashboard/NodeDiscovery/IProcessingServer.Consul.cs View File

@@ -0,0 +1,35 @@
// Copyright (c) .NET Core Community. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

namespace DotNetCore.CAP.Dashboard.NodeDiscovery
{
internal class ConsulProcessingNodeServer : IProcessingServer
{
private readonly DiscoveryOptions _dashboardOptions;
private readonly IDiscoveryProviderFactory _discoveryProviderFactory;

public ConsulProcessingNodeServer(
DiscoveryOptions dashboardOptions,
IDiscoveryProviderFactory discoveryProviderFactory)
{
_dashboardOptions = dashboardOptions;
_discoveryProviderFactory = discoveryProviderFactory;
}

public void Start()
{
var discoveryProvider = _discoveryProviderFactory.Create(_dashboardOptions);

discoveryProvider.RegisterNode();
}

public void Pulse()
{
//ignore
}

public void Dispose()
{
}
}
}

+ 18
- 0
src/DotNetCore.CAP.Dashboard/NodeDiscovery/Node.cs View File

@@ -0,0 +1,18 @@
// Copyright (c) .NET Core Community. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

namespace DotNetCore.CAP.Dashboard.NodeDiscovery
{
public class Node
{
public string Id { get; set; }

public string Name { get; set; }

public string Address { get; set; }

public int Port { get; set; }

public string Tags { get; set; }
}
}

Loading…
Cancel
Save