Skip to content

Instantly share code, notes, and snippets.

@Manuel-S
Created November 27, 2017 15:19
Show Gist options
  • Select an option

  • Save Manuel-S/2cac9ebc6234c70e2eae9eda4b7bb341 to your computer and use it in GitHub Desktop.

Select an option

Save Manuel-S/2cac9ebc6234c70e2eae9eda4b7bb341 to your computer and use it in GitHub Desktop.
lightweight consul c# client library
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
namespace Consul
{
public partial class ConsulService : IDisposable
{
private string serviceId;
private string serviceName;
private string deregisterAfter;
private string version;
private string healthCheckMethod;
private string address;
private int port;
private Task task;
private int sleepInterval = 15000;
private bool shutdown;
public Uri BaseUri { get; }
private async void ThreadStart()
{
bool registered = false;
var client = new HttpClient()
{
BaseAddress = BaseUri
};
while (!shutdown)
{
if (!registered)
{
try
{
registered = await RegisterServiceAsync(client);
}
catch
{
registered = false;
}
}
else
{
try
{
registered = await CheckRegisteredAsync(client);
}
catch
{
registered = false;
}
}
await Task.Delay(sleepInterval);
}
}
private async Task<bool> CheckRegisteredAsync(HttpClient client)
{
var response = await client.GetAsync("v1/agent/services");
var content = await response.Content.ReadAsAsync<Dictionary<string, object>>();
return content.ContainsKey(serviceId);
}
private async Task<bool> RegisterServiceAsync(HttpClient client)
{
return (await client.PutAsJsonAsync("v1/agent/service/register",
new
{
Name = serviceName,
ID = serviceId,
Address = address,
Port = port,
Tags = string.IsNullOrWhiteSpace(version) ? new string[0] : new[] { version },
EnableTagOverride = false,
Checks = string.IsNullOrWhiteSpace(healthCheckMethod) ?
new object[0] :
new[] {
new
{
Name = "Health",
Interval = "10s",
DeregisterCriticalServiceAfter = deregisterAfter,
HTTP = $"{address}:{port}/{healthCheckMethod}"
}
},
CreateIndex = 0,
ModifyIndex = 0
}))
.IsSuccessStatusCode;
}
public ConsulService(string address, int port, string serviceName, Uri consulUri = null,
string deregisterAfter = "4m", string version = null, string healthCheckMethod = "status")
{
serviceId = serviceName + "-" + Guid.NewGuid();
BaseUri = consulUri ?? ConsulDefaultUri;
this.serviceName = serviceName;
this.deregisterAfter = deregisterAfter;
this.version = version;
this.healthCheckMethod = healthCheckMethod;
this.address = address;
this.port = port;
task = new Task(ThreadStart);
task.Start();
}
public void Dispose()
{
shutdown = true;
var client = new HttpClient();
client.GetAsync(new Uri(BaseUri, $"v1/agent/service/deregister/{serviceId}")).Wait();
task.Wait();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using System.Net.NetworkInformation;
namespace Consul
{
public partial class ConsulService
{
public static Uri ConsulDefaultUri { get; set; } = new Uri("http://localhost:8500");
public static async Task<HttpClient> GetServiceAsync(string serviceName,
Uri consulUri = null,
string version = null)
{
var rng = new Random();
consulUri = consulUri ?? ConsulDefaultUri;
var client = new HttpClient();
try
{
var response = await client.GetAsync(new Uri(consulUri, "/v1/agent/services"));
var results = await response.Content.ReadAsAsync<Dictionary<string, ServiceQueryResult>>();
var services =
results.Select(x => x.Value).Where(x => x.Service.Equals(serviceName, StringComparison.InvariantCultureIgnoreCase)
&& (version == null || x.Tags.Contains(version))
).ToList();
if (!services.Any())
return null;
var service = services[rng.Next(0, services.Count)];
return new HttpClient()
{
BaseAddress = new Uri($"{service.Address}:{service.Port}")
};
}
catch (Exception ex)
{
return null;
}
}
public static int GetAvailablePort(int startingPort)
{
var properties = IPGlobalProperties.GetIPGlobalProperties();
return Enumerable.Range(startingPort, UInt16.MaxValue)
.Except(properties.GetActiveTcpConnections().Select(n => n.LocalEndPoint.Port))
.Except(properties.GetActiveTcpListeners().Select(n => n.Port))
.Except(properties.GetActiveUdpListeners().Select(n => n.Port))
.FirstOrDefault();
}
private class ServiceQueryResult
{
public string ID { get; set; }
public string Service { get; set; }
public string[] Tags { get; set; }
public string Address { get; set; }
public int Port { get; set; }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment