Created
November 27, 2017 15:19
-
-
Save Manuel-S/2cac9ebc6234c70e2eae9eda4b7bb341 to your computer and use it in GitHub Desktop.
lightweight consul c# client library
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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(); | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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