Skip to content

Commit

Permalink
Limit Client Connections (#828)
Browse files Browse the repository at this point in the history
* expose connection limit option

* implement connection limit at handle new connection

* addressing comments

* fix unlimited connection limit

* release v1.0.45
  • Loading branch information
vazois authored Nov 26, 2024
1 parent eeec78c commit 996a40a
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 5 deletions.
2 changes: 1 addition & 1 deletion Version.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project>
<!-- Versioning property for builds and packages -->
<PropertyGroup>
<VersionPrefix>1.0.44</VersionPrefix>
<VersionPrefix>1.0.45</VersionPrefix>
</PropertyGroup>
</Project>
5 changes: 5 additions & 0 deletions libs/host/Configuration/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down Expand Up @@ -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),
Expand Down
2 changes: 1 addition & 1 deletion libs/host/GarnetServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions libs/host/defaults.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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,

Expand Down
5 changes: 5 additions & 0 deletions libs/server/Servers/GarnetServerOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,11 @@ public class GarnetServerOptions : ServerOptions
/// </summary>
public int ThreadPoolMaxThreads = 0;

/// <summary>
/// Maximum client connection limit
/// </summary>
public int NetworkConnectionLimit = -1;

/// <summary>
/// Creator of device factories
/// </summary>
Expand Down
13 changes: 10 additions & 3 deletions libs/server/Servers/GarnetServerTcp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class GarnetServerTcp : GarnetServerBase, IServerHook
readonly int networkSendThrottleMax;
readonly NetworkBufferSettings networkBufferSettings;
readonly LimitedFixedBufferPool networkPool;
readonly int networkConnectionLimit;

public IPEndPoint GetEndPoint
{
Expand Down Expand Up @@ -69,9 +70,10 @@ public IEnumerable<IClusterSession> ActiveClusterSessions()
/// <param name="tlsOptions"></param>
/// <param name="networkSendThrottleMax"></param>
/// <param name="logger"></param>
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());
Expand Down Expand Up @@ -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
{
Expand All @@ -157,6 +159,11 @@ private unsafe bool HandleNewConnection(SocketAsyncEventArgs e)
handler?.Dispose();
}
}
else
{
Interlocked.Decrement(ref activeHandlerCount);
e.AcceptSocket.Dispose();
}
}
return true;
}
Expand Down

0 comments on commit 996a40a

Please sign in to comment.