diff --git a/src/Microsoft.Azure.SignalR.Common/Endpoints/EndpointRoutingMode.cs b/src/Microsoft.Azure.SignalR.Common/Endpoints/EndpointRoutingMode.cs
deleted file mode 100644
index aefa0202d..000000000
--- a/src/Microsoft.Azure.SignalR.Common/Endpoints/EndpointRoutingMode.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-namespace Microsoft.Azure.SignalR
-{
- public enum EndpointRoutingMode
- {
- ///
- /// Choose endpoint randomly by weight.
- /// The weight is defined as (the remaining connection quota / the connection capacity).
- /// This is the default mode.
- ///
- Weighted,
-
- ///
- /// Choose the endpoint with least connection count.
- /// This mode distributes connections evenly among endpoints.
- ///
- LeastConnection,
-
- ///
- /// Choose the endpoint randomly
- ///
- Random,
- }
-}
\ No newline at end of file
diff --git a/src/Microsoft.Azure.SignalR/EndpointRouters/DefaultEndpointRouter.cs b/src/Microsoft.Azure.SignalR/EndpointRouters/DefaultEndpointRouter.cs
index c185fccb3..a00c726cd 100644
--- a/src/Microsoft.Azure.SignalR/EndpointRouters/DefaultEndpointRouter.cs
+++ b/src/Microsoft.Azure.SignalR/EndpointRouters/DefaultEndpointRouter.cs
@@ -6,21 +6,13 @@
using System.Linq;
using Microsoft.AspNetCore.Http;
using Microsoft.Azure.SignalR.Common;
-using Microsoft.Extensions.Options;
namespace Microsoft.Azure.SignalR
{
internal class DefaultEndpointRouter : DefaultMessageRouter, IEndpointRouter
{
- private readonly EndpointRoutingMode _mode;
-
- public DefaultEndpointRouter(IOptions options)
- {
- _mode = options?.Value.EndpointRoutingMode ?? EndpointRoutingMode.Weighted;
- }
-
///
- /// Select an endpoint for negotiate request according to the mode
+ /// Select an endpoint for negotiate request
///
/// The http context of the incoming request
/// All the available endpoints
@@ -28,12 +20,7 @@ public ServiceEndpoint GetNegotiateEndpoint(HttpContext context, IEnumerable GetEndpointRandomly(availableEndpoints),
- EndpointRoutingMode.LeastConnection => GetEndpointWithLeastConnection(availableEndpoints),
- _ => GetEndpointAccordingToWeight(availableEndpoints),
- };
+ return GetEndpointAccordingToWeight(availableEndpoints);
}
///
@@ -69,7 +56,7 @@ private ServiceEndpoint GetEndpointAccordingToWeight(ServiceEndpoint[] available
if (availableEndpoints.Any(endpoint => endpoint.EndpointMetrics.ConnectionCapacity == 0) ||
availableEndpoints.Length == 1)
{
- return GetEndpointRandomly(availableEndpoints);
+ return availableEndpoints[StaticRandom.Next(availableEndpoints.Length)];
}
var we = new int[availableEndpoints.Length];
@@ -89,38 +76,5 @@ private ServiceEndpoint GetEndpointAccordingToWeight(ServiceEndpoint[] available
return availableEndpoints[Array.FindLastIndex(we, x => x <= index) + 1];
}
-
- ///
- /// Choose endpoint with least connection count
- ///
- private ServiceEndpoint GetEndpointWithLeastConnection(ServiceEndpoint[] availableEndpoints)
- {
- //first check if weight is available or necessary
- if (availableEndpoints.Any(endpoint => endpoint.EndpointMetrics.ConnectionCapacity == 0) ||
- availableEndpoints.Length == 1)
- {
- return GetEndpointRandomly(availableEndpoints);
- }
-
- var leastConnectionCount = int.MaxValue;
- var index = 0;
- for (var i = 0; i < availableEndpoints.Length; i++)
- {
- var endpointMetrics = availableEndpoints[i].EndpointMetrics;
- var connectionCount = endpointMetrics.ClientConnectionCount + endpointMetrics.ServerConnectionCount;
- if (connectionCount < leastConnectionCount)
- {
- leastConnectionCount = connectionCount;
- index = i;
- }
- }
-
- return availableEndpoints[index];
- }
-
- private static ServiceEndpoint GetEndpointRandomly(ServiceEndpoint[] availableEndpoints)
- {
- return availableEndpoints[StaticRandom.Next(availableEndpoints.Length)];
- }
}
}
\ No newline at end of file
diff --git a/src/Microsoft.Azure.SignalR/EndpointRouters/EndpointRouterDecorator.cs b/src/Microsoft.Azure.SignalR/EndpointRouters/EndpointRouterDecorator.cs
index 851f6967e..3618e9361 100644
--- a/src/Microsoft.Azure.SignalR/EndpointRouters/EndpointRouterDecorator.cs
+++ b/src/Microsoft.Azure.SignalR/EndpointRouters/EndpointRouterDecorator.cs
@@ -12,7 +12,7 @@ public class EndpointRouterDecorator : IEndpointRouter
public EndpointRouterDecorator(IEndpointRouter router = null)
{
- _inner = router ?? new DefaultEndpointRouter(null);
+ _inner = router ?? new DefaultEndpointRouter();
}
public virtual ServiceEndpoint GetNegotiateEndpoint(HttpContext context, IEnumerable endpoints)
diff --git a/src/Microsoft.Azure.SignalR/ServiceOptions.cs b/src/Microsoft.Azure.SignalR/ServiceOptions.cs
index f301a6909..9160b147a 100644
--- a/src/Microsoft.Azure.SignalR/ServiceOptions.cs
+++ b/src/Microsoft.Azure.SignalR/ServiceOptions.cs
@@ -121,11 +121,5 @@ public int ConnectionCount
/// Gets or sets a function which accepts and returns a bitmask combining one or more values that specify what transports the service should use to receive HTTP requests.
///
public Func TransportTypeDetector { get; set; } = null;
-
- ///
- /// Gets or sets the default endpoint routing mode when using multiple endpoints.
- /// by default.
- ///
- public EndpointRoutingMode EndpointRoutingMode { get; set; } = EndpointRoutingMode.Weighted;
}
}
diff --git a/test/Microsoft.Azure.SignalR.Tests/EndpointRouterTests.cs b/test/Microsoft.Azure.SignalR.Tests/EndpointRouterTests.cs
index e4e4e8ffc..e329a1e8c 100644
--- a/test/Microsoft.Azure.SignalR.Tests/EndpointRouterTests.cs
+++ b/test/Microsoft.Azure.SignalR.Tests/EndpointRouterTests.cs
@@ -3,8 +3,6 @@
using System;
using System.Collections.Generic;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
using Xunit;
namespace Microsoft.Azure.SignalR.Tests
@@ -14,7 +12,7 @@ public class EndpointRouterTests
[Fact]
public void TestDefaultEndpointRouterWeightedMode()
{
- var drt = GetEndpointRouter(EndpointRoutingMode.Weighted);
+ var drt = new DefaultEndpointRouter();
const int loops = 20;
var context = new RandomContext();
@@ -37,46 +35,43 @@ public void TestDefaultEndpointRouterWeightedMode()
context.Reset();
}
- [Fact]
- public void TestDefaultEndpointRouterLeastConnectionMode()
+ [Theory]
+ [InlineData(200)]
+ [InlineData(300)]
+ [InlineData(400)]
+ [InlineData(500)]
+ public void TestDefaultEndpointRouterWeightedModeWhenAutoScaleIsEnabled(int quotaOfScaleUpInstance)
{
- var drt = GetEndpointRouter(EndpointRoutingMode.LeastConnection);
+ var drt = new DefaultEndpointRouter();
- const int loops = 10;
+ var loops = 100 + (quotaOfScaleUpInstance / 5);
var context = new RandomContext();
+ const double quotaBarForScaleUp = 0.8;
- const string small = "small_instance", large = "large_instance";
- var uSmall = GenerateServiceEndpoint(100, 0, 90, small);
- var uLarge = GenerateServiceEndpoint(1000, 0, 200, large);
- var el = new List() { uLarge, uSmall };
+ var endpointA = GenerateServiceEndpoint(quotaOfScaleUpInstance, 0, 80, "a");
+ var endpointB = GenerateServiceEndpoint(100, 0, 70, "b");
+ var endpointC = GenerateServiceEndpoint(100, 0, 70, "c");
+ var el = new List() {endpointA, endpointB, endpointC};
context.BenchTest(loops, () =>
{
var ep = drt.GetNegotiateEndpoint(null, el);
ep.EndpointMetrics.ClientConnectionCount++;
+ var percent = (ep.EndpointMetrics.ClientConnectionCount + ep.EndpointMetrics.ServerConnectionCount) /
+ (double)ep.EndpointMetrics.ConnectionCapacity;
+ if (percent > quotaBarForScaleUp)
+ {
+ ep.EndpointMetrics.ConnectionCapacity += 100;
+ }
+
return ep.Name;
});
- var uLargeCount = context.GetCount(large);
- var uSmallCount = context.GetCount(small);
- Assert.Equal(0, uLargeCount);
- Assert.Equal(10, uSmallCount);
- context.Reset();
- }
- private static IEndpointRouter GetEndpointRouter(EndpointRoutingMode mode)
- {
- var config = new ConfigurationBuilder().Build();
- var serviceProvider = new ServiceCollection()
- .AddSignalR()
- .AddAzureSignalR(
- o =>
- {
- o.EndpointRoutingMode = mode;
- })
- .Services
- .AddSingleton(config)
- .BuildServiceProvider();
+ Assert.Equal(context.GetCount("a") + context.GetCount("b") + context.GetCount("c"), loops);
+ Assert.Equal(quotaOfScaleUpInstance, endpointA.EndpointMetrics.ConnectionCapacity);
+ Assert.Equal(200, endpointB.EndpointMetrics.ConnectionCapacity);
+ Assert.Equal(200, endpointC.EndpointMetrics.ConnectionCapacity);
- return serviceProvider.GetRequiredService();
+ context.Reset();
}
private static ServiceEndpoint GenerateServiceEndpoint(int capacity, int serverConnectionCount,
diff --git a/test/Microsoft.Azure.SignalR.Tests/MultiEndpointServiceConnectionContainerTests.cs b/test/Microsoft.Azure.SignalR.Tests/MultiEndpointServiceConnectionContainerTests.cs
index 40eae490f..4493b6f64 100644
--- a/test/Microsoft.Azure.SignalR.Tests/MultiEndpointServiceConnectionContainerTests.cs
+++ b/test/Microsoft.Azure.SignalR.Tests/MultiEndpointServiceConnectionContainerTests.cs
@@ -245,7 +245,7 @@ public async Task TestContainerWithOneEndpointWithAllDisconnectedConnectionThrow
{
var endpoint = new ServiceEndpoint(ConnectionString1);
var sem = new TestServiceEndpointManager(endpoint);
- var router = new DefaultEndpointRouter(null);
+ var router = new DefaultEndpointRouter();
var container = new TestMultiEndpointServiceConnectionContainer("hub",
e => new TestServiceConnectionContainer(new List {