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 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); }