diff --git a/Version.props b/Version.props
index e3b95fd3cb..97df7ba6f4 100644
--- a/Version.props
+++ b/Version.props
@@ -1,6 +1,6 @@
- 1.0.44
+ 1.0.45
\ No newline at end of file
diff --git a/libs/host/Configuration/Options.cs b/libs/host/Configuration/Options.cs
index 95592b8eb5..96fdd62433 100644
--- a/libs/host/Configuration/Options.cs
+++ b/libs/host/Configuration/Options.cs
@@ -339,6 +339,10 @@ internal sealed class Options
[Option("maxthreads", Required = false, HelpText = "Maximum worker and completion threads in thread pool, 0 uses the system default.")]
public int ThreadPoolMaxThreads { get; set; }
+ [IntRangeValidation(-1, int.MaxValue)]
+ [Option("network-connection-limit", Required = false, Default = -1, HelpText = "Maximum number of simultaneously active network connections.")]
+ public int NetworkConnectionLimit { get; set; }
+
[OptionValidation]
[Option("use-azure-storage", Required = false, HelpText = "Use Azure Page Blobs for storage instead of local storage.")]
public bool? UseAzureStorage { get; set; }
@@ -676,6 +680,7 @@ public GarnetServerOptions GetServerOptions(ILogger logger = null)
QuietMode = QuietMode.GetValueOrDefault(),
ThreadPoolMinThreads = ThreadPoolMinThreads,
ThreadPoolMaxThreads = ThreadPoolMaxThreads,
+ NetworkConnectionLimit = NetworkConnectionLimit,
DeviceFactoryCreator = useAzureStorage
? () => new AzureStorageNamedDeviceFactory(AzureStorageConnectionString, logger)
: () => new LocalStorageNamedDeviceFactory(useNativeDeviceLinux: UseNativeDeviceLinux.GetValueOrDefault(), logger: logger),
diff --git a/libs/host/GarnetServer.cs b/libs/host/GarnetServer.cs
index db9f912824..32389d8aa6 100644
--- a/libs/host/GarnetServer.cs
+++ b/libs/host/GarnetServer.cs
@@ -216,7 +216,7 @@ private void InitializeServer()
}
// Create Garnet TCP server if none was provided.
- this.server ??= new GarnetServerTcp(opts.Address, opts.Port, 0, opts.TlsOptions, opts.NetworkSendThrottleMax, logger);
+ this.server ??= new GarnetServerTcp(opts.Address, opts.Port, 0, opts.TlsOptions, opts.NetworkSendThrottleMax, opts.NetworkConnectionLimit, logger);
storeWrapper = new StoreWrapper(version, redisProtocolVersion, server, store, objectStore, objectStoreSizeTracker,
customCommandManager, appendOnlyFile, opts, clusterFactory: clusterFactory, loggerFactory: loggerFactory);
diff --git a/libs/host/defaults.conf b/libs/host/defaults.conf
index 5b4c66d9fe..aa18841004 100644
--- a/libs/host/defaults.conf
+++ b/libs/host/defaults.conf
@@ -251,6 +251,9 @@
/* Maximum worker and completion threads in thread pool, 0 uses the system default. */
"ThreadPoolMaxThreads" : 0,
+ /* Maximum number of simultaneously active network connections. */
+ "NetworkConnectionLimit" : -1,
+
/* Use Azure Page Blobs for storage instead of local storage. */
"UseAzureStorage" : false,
diff --git a/libs/server/Servers/GarnetServerOptions.cs b/libs/server/Servers/GarnetServerOptions.cs
index 465d9b77e2..0093cfd8e0 100644
--- a/libs/server/Servers/GarnetServerOptions.cs
+++ b/libs/server/Servers/GarnetServerOptions.cs
@@ -246,6 +246,11 @@ public class GarnetServerOptions : ServerOptions
///
public int ThreadPoolMaxThreads = 0;
+ ///
+ /// Maximum client connection limit
+ ///
+ public int NetworkConnectionLimit = -1;
+
///
/// Creator of device factories
///
diff --git a/libs/server/Servers/GarnetServerTcp.cs b/libs/server/Servers/GarnetServerTcp.cs
index 017248d122..09a1c4fd71 100644
--- a/libs/server/Servers/GarnetServerTcp.cs
+++ b/libs/server/Servers/GarnetServerTcp.cs
@@ -24,6 +24,7 @@ public class GarnetServerTcp : GarnetServerBase, IServerHook
readonly int networkSendThrottleMax;
readonly NetworkBufferSettings networkBufferSettings;
readonly LimitedFixedBufferPool networkPool;
+ readonly int networkConnectionLimit;
public IPEndPoint GetEndPoint
{
@@ -69,9 +70,10 @@ public IEnumerable ActiveClusterSessions()
///
///
///
- public GarnetServerTcp(string address, int port, int networkBufferSize = default, IGarnetTlsOptions tlsOptions = null, int networkSendThrottleMax = 8, ILogger logger = null)
+ public GarnetServerTcp(string address, int port, int networkBufferSize = default, IGarnetTlsOptions tlsOptions = null, int networkSendThrottleMax = 8, int networkConnectionLimit = -1, ILogger logger = null)
: base(address, port, networkBufferSize, logger)
{
+ this.networkConnectionLimit = networkConnectionLimit;
this.tlsOptions = tlsOptions;
this.networkSendThrottleMax = networkSendThrottleMax;
var serverBufferSize = BufferSizeUtils.ServerBufferSize(new MaxSizeSettings());
@@ -134,11 +136,11 @@ private unsafe bool HandleNewConnection(SocketAsyncEventArgs e)
string remoteEndpointName = e.AcceptSocket.RemoteEndPoint?.ToString();
logger?.LogDebug("Accepted TCP connection from {remoteEndpoint}", remoteEndpointName);
-
ServerTcpNetworkHandler handler = null;
if (activeHandlerCount >= 0)
{
- if (Interlocked.Increment(ref activeHandlerCount) > 0)
+ var currentActiveHandlerCount = Interlocked.Increment(ref activeHandlerCount);
+ if (currentActiveHandlerCount > 0 && (networkConnectionLimit == -1 || currentActiveHandlerCount <= networkConnectionLimit))
{
try
{
@@ -157,6 +159,11 @@ private unsafe bool HandleNewConnection(SocketAsyncEventArgs e)
handler?.Dispose();
}
}
+ else
+ {
+ Interlocked.Decrement(ref activeHandlerCount);
+ e.AcceptSocket.Dispose();
+ }
}
return true;
}