Пример #1
0
        public async Task <StatusResponse> Get(
            [FromServices] ILoadBalancer registry,
            [FromServices] IHttpClientFactory factory,
            [FromServices] ILogger <StatusController> logger)
        {
            var configHosts = registry.GetConfig();

            logger.LogInformation("STATUS request with {0} hosts configured", configHosts.Length);

            using var client = factory.CreateClient("status");

            async Task <string?> GetStatus(Uri statusUri, CancellationToken token)
            {
                try
                {
                    var response = await client.GetAsync(statusUri, HttpCompletionOption.ResponseContentRead, token);

                    if (response.IsSuccessStatusCode)
                    {
                        var responseContent = await response.Content.ReadAsStringAsync();

                        return(responseContent);
                    }

                    logger.LogError("Error getting /STATUS from {0}: got {1}", statusUri, response.StatusCode);
                    return(null);
                }
                catch (Exception e)
                {
                    logger.LogError("Error getting /STATUS from {0}: {1}", statusUri, e.Message);
                    return(null);
                }
            }

            var cts       = new CancellationTokenSource(4000);
            var responses = await Task.WhenAll(
                from host in configHosts
                let statusUri = new Uri(new Uri(host.HostUri), "/status")
                select GetStatus(statusUri, cts.Token)
                );

            var stats = new StatusResponse();

            foreach (var statusPayload in responses.Where(r => !string.IsNullOrEmpty(r)))
            {
                var hs = JsonSerializer.Deserialize <StatusResponse>(statusPayload);
                stats.Merge(hs);
            }

            return(stats);
        }
Пример #2
0
        private async Task SyncConfig(CancellationToken cancellationToken)
        {
            var runningHosts = _balancer.GetConfig().ToDictionary(c => new Uri(c.HostUri), c => c);
            var newConfig    = _configOptions.CurrentValue;
            var newHosts     = newConfig.Hosts.ToDictionary(c => new Uri(c.HostUri), c => c);

            // TODO optimize alive-ness request
            // var consideredAlive = _sessionHandler.GetAliveHosts(DateTimeOffset.Now - TimeSpan.FromSeconds(30));

            var hostsStatus = await CheckAliveStatus(from h in newConfig.Hosts select new Uri(h.HostUri));

            Predicate <Uri> isAlive = uri =>
                                      hostsStatus.TryGetValue(uri, out var x) && x &&
                                      newHosts.TryGetValue(uri, out var config) && config.Limit > 0;

            var toBeRemoved =
                (from host in runningHosts.Keys
                 where !newHosts.ContainsKey(host) || !isAlive(host)
                 select host).ToArray();
            var toBeStarted =
                (from host in newHosts.Keys
                 where (!runningHosts.ContainsKey(host) || !areConfigsEqual(newHosts[host], runningHosts[host])) && isAlive(host)
                 select host).ToArray();

            if (toBeRemoved.Any() || toBeStarted.Any())
            {
                _logger.LogInformation("Detected changes in configuration or availability of the hosts");
            }

            await Task.WhenAll(
                from host in toBeRemoved
                select _balancer.DeleteHost(host)
                );

            await Task.WhenAll(
                from host in toBeStarted
                select _balancer.AddHost(newHosts[host])
                );

            // TODO update status monitor queue
            // if (hostsStatus.Any(status => status.Value == false))
            // {
            //  var deadHosts = from h in newConfig.Hosts where !isAlive(h.HostUri) select h.HostUri;
            //  _logger.LogWarning("Hosts not available: {0}", string.Join(", ", deadHosts.ToArray()));
            // }
        }