protected static Channel TryGetChannelFromLoadBalancer(Channel lbChannel, ChannelCredentials credentials, string serviceName, int maxMesssageLength) { ServiceDiscoveryGrpc.ServiceDiscoveryGrpcClient lbClient = new ServiceDiscoveryGrpc.ServiceDiscoveryGrpcClient(lbChannel); DiscoverServicesResponse lbResponse = lbClient.DiscoverTopServices( new DiscoverServicesRequest { ServiceName = serviceName, MaxCount = 1 }); if (lbResponse.ServiceLocations.Count > 0) { ServiceLocationMsg serviceLocation = lbResponse.ServiceLocations[0]; Channel result = GrpcUtils.CreateChannel(serviceLocation.HostName, serviceLocation.Port, credentials, maxMesssageLength); _msg.DebugFormat("The load balancer is suggesting {0}", result.ResolvedTarget); return(result); } // Assumption: A load balancer is never also serving real requests -> lets not use it at all! _msg.Debug("The load balancer has no service locations available."); return(null); }
public override async Task <DiscoverServicesResponse> DiscoverTopServices( DiscoverServicesRequest request, ServerCallContext context) { DiscoverServicesResponse response = null; try { ProcessUtils.EnsureThreadIdInName(); Stopwatch watch = Stopwatch.StartNew(); response = new DiscoverServicesResponse(); IList <ServiceLocationMsg> result = await GetTopServiceLocationMessages(request); response.ServiceLocations.AddRange(result); _logger.LogDebug( "Returning {count} service location(s) [{time}ms]: {serviceLocations}", result.Count, watch.ElapsedMilliseconds, string.Concat(result.Select(s => $"{s.HostName}:{s.Port}, "))); } catch (Exception e) { _logger.LogError(e, "Error discovering service {serviceName}", request.ServiceName); SetUnhealthy(); } return(response); }
public void CanDiscoverSingleService() { DeregisterServices(_host127001, _startPort127001); ServiceDiscoveryGrpc.ServiceDiscoveryGrpcClient client = GetClient(); DiscoverServicesResponse response = client.DiscoverServices( new DiscoverServicesRequest { ServiceName = _serviceName, MaxCount = 1 }); Assert.AreEqual(1, response.ServiceLocations.Count); ServiceLocationMsg serviceLocation = response.ServiceLocations[0]; Assert.AreEqual(_serviceName, serviceLocation.ServiceName); Assert.AreEqual(_localHost, serviceLocation.HostName); }
public void CanDiscoverManyServices() { DeregisterServices(_host127001, _startPort127001); ServiceDiscoveryGrpc.ServiceDiscoveryGrpcClient client = GetClient(); DiscoverServicesResponse response = client.DiscoverServices( new DiscoverServicesRequest { ServiceName = _serviceName, MaxCount = 3 }); Assert.AreEqual(3, response.ServiceLocations.Count); foreach (var serviceLocation in response.ServiceLocations) { Assert.AreEqual(_serviceName, serviceLocation.ServiceName); Assert.AreEqual(_localHost, serviceLocation.HostName); Assert.True(serviceLocation.Port >= _startPort && serviceLocation.Port < _startPort + _serviceCount); } }
public void CanBalanceMultiMachineLoad() { // Add a 'second host' with a different name (127.0.0.1 vs localhost) StartAndRegisterServices(_host127001, _startPort127001); // Wait until the least recently used service cache can be cleared // (it could contain ports from previous tests) Thread.Sleep(5000); ServiceDiscoveryGrpc.ServiceDiscoveryGrpcClient client = GetClient(); // All load at 0 var singleServiceRequest = new DiscoverServicesRequest { ServiceName = _serviceName, MaxCount = 1 }; DiscoverServicesResponse response = client.DiscoverTopServices(singleServiceRequest); Assert.AreEqual(1, response.ServiceLocations.Count); // If all else is equal, they are ordered by port ServiceLocation serviceLocation = ToServiceLocation(response.ServiceLocations[0]); Assert.AreEqual(_serviceName, serviceLocation.ServiceName); string firstLocationHost = serviceLocation.HostName; // Add one load to the first machine: _serviceLoadByLocation[serviceLocation].CurrentProcessCount += 1; // The second time, thanks to machine-level cpu balancing the first port from the other // machine should be returned: response = client.DiscoverTopServices(singleServiceRequest); Assert.AreEqual(1, response.ServiceLocations.Count); serviceLocation = ToServiceLocation(response.ServiceLocations[0]); Assert.AreEqual(_serviceName, serviceLocation.ServiceName); Assert.AreNotEqual(firstLocationHost, serviceLocation.HostName); foreach (KeyValuePair <ServiceLocation, ServiceLoad> loadByPort in _serviceLoadByLocation) { if (loadByPort.Key.HostName == _localHost) { continue; } // Overload the 127.0.0.1 host completely: int ascendingRank = loadByPort.Key.Port - _startPort127001; int descendingRank = _serviceCount - ascendingRank; loadByPort.Value.CurrentProcessCount = descendingRank; } Stopwatch watch = Stopwatch.StartNew(); response = client.DiscoverTopServices( new DiscoverServicesRequest { ServiceName = _serviceName, MaxCount = 6 }); watch.Stop(); Console.WriteLine("First time full balancing: {0}ms", watch.ElapsedMilliseconds); Assert.AreEqual(6, response.ServiceLocations.Count); HashSet <int> usedPorts = new HashSet <int>(); for (var i = 0; i < response.ServiceLocations.Count; i++) { serviceLocation = ToServiceLocation(response.ServiceLocations[i]); Assert.AreEqual(_serviceName, serviceLocation.ServiceName); Assert.AreEqual(_localHost, serviceLocation.HostName); Assert.True(serviceLocation.Port >= _startPort && serviceLocation.Port < _startPort + _serviceCount); usedPorts.Add(serviceLocation.Port); } // Assert performance after warm-up: watch = Stopwatch.StartNew(); response = client.DiscoverTopServices( new DiscoverServicesRequest { ServiceName = _serviceName, MaxCount = 4 }); Assert.AreEqual(4, response.ServiceLocations.Count); watch.Stop(); Console.WriteLine("Second time full balancing (warm channels): {0}ms", watch.ElapsedMilliseconds); Assert.Less(watch.ElapsedMilliseconds, 50); for (var i = 0; i < response.ServiceLocations.Count; i++) { serviceLocation = ToServiceLocation(response.ServiceLocations[i]); Assert.AreEqual(_serviceName, serviceLocation.ServiceName); Assert.AreEqual(_localHost, serviceLocation.HostName); Assert.True(serviceLocation.Port >= _startPort && serviceLocation.Port < _startPort + _serviceCount); Assert.IsFalse(usedPorts.Contains(serviceLocation.Port)); } DeregisterServices(_host127001, _startPort127001); }
public void CanBalanceLoad() { ServiceDiscoveryGrpc.ServiceDiscoveryGrpcClient client = GetClient(); // All load at 0 var singleServiceRequest = new DiscoverServicesRequest { ServiceName = _serviceName, MaxCount = 1 }; DiscoverServicesResponse response = client.DiscoverTopServices(singleServiceRequest); Assert.AreEqual(1, response.ServiceLocations.Count); // If all else is equal, they are ordered by port var serviceLocation = response.ServiceLocations[0]; Assert.AreEqual(_serviceName, serviceLocation.ServiceName); Assert.AreEqual(_localHost, serviceLocation.HostName); Assert.AreEqual(_startPort, serviceLocation.Port); // The second time, thanks to some kind of round-robin among the least recently used // a different port should be returned: response = client.DiscoverTopServices(singleServiceRequest); Assert.AreEqual(1, response.ServiceLocations.Count); serviceLocation = response.ServiceLocations[0]; Assert.AreEqual(_serviceName, serviceLocation.ServiceName); Assert.AreEqual(_localHost, serviceLocation.HostName); Assert.AreNotEqual(_startPort, serviceLocation.Port); foreach (KeyValuePair <ServiceLocation, ServiceLoad> loadByPort in _serviceLoadByLocation) { // Order by port but descending int ascendingRank = loadByPort.Key.Port - _startPort; int descendingRank = _serviceCount - ascendingRank; loadByPort.Value.CurrentProcessCount = descendingRank; } Stopwatch watch = Stopwatch.StartNew(); response = client.DiscoverTopServices( new DiscoverServicesRequest { ServiceName = _serviceName, MaxCount = 3 }); watch.Stop(); Console.WriteLine("First time full balancing: {0}ms", watch.ElapsedMilliseconds); Assert.AreEqual(3, response.ServiceLocations.Count); for (var i = 0; i < response.ServiceLocations.Count; i++) { serviceLocation = response.ServiceLocations[i]; Assert.AreEqual(_serviceName, serviceLocation.ServiceName); Assert.AreEqual(_localHost, serviceLocation.HostName); int expected = _startPort + _serviceCount - i - 1; Assert.AreEqual(expected, serviceLocation.Port); Assert.True(serviceLocation.Port >= _startPort && serviceLocation.Port < _startPort + _serviceCount); } // Assert performance after warm-up: watch = Stopwatch.StartNew(); response = client.DiscoverTopServices( new DiscoverServicesRequest { ServiceName = _serviceName, MaxCount = 3 }); Assert.AreEqual(3, response.ServiceLocations.Count); watch.Stop(); Console.WriteLine("Second time full balancing (warm channels): {0}ms", watch.ElapsedMilliseconds); Assert.Less(watch.ElapsedMilliseconds, 50); }