Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(slimfaas): scale down #66

Merged
merged 14 commits into from
Jun 26, 2024
2 changes: 1 addition & 1 deletion src/SlimData/SlimData.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="DotNext.AspNetCore.Cluster" Version="5.6.0" />
<PackageReference Include="DotNext.AspNetCore.Cluster" Version="5.7.0" />
<PackageReference Include="MemoryPack" Version="1.21.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
</ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/SlimData/SlimPersistentState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@
public CommandInterpreter Interpreter { get; }

public SlimPersistentState(string path)
: base(path, 50, new Options { InitialPartitionSize = 50 * 8, UseCaching = true, UseLegacyBinaryFormat = true })
: base(path, 50, new Options { InitialPartitionSize = 50 * 80, UseCaching = true, UseLegacyBinaryFormat = true })

Check warning on line 20 in src/SlimData/SlimPersistentState.cs

View workflow job for this annotation

GitHub Actions / SonarCloud

'PersistentState.Options.UseLegacyBinaryFormat' is obsolete: 'Use default format instead.'

Check warning on line 20 in src/SlimData/SlimPersistentState.cs

View workflow job for this annotation

GitHub Actions / SonarCloud

'PersistentState.Options.UseLegacyBinaryFormat' is obsolete: 'Use default format instead.'
{
Interpreter = SlimDataInterpreter.InitInterpreter(_state);
}

public SlimPersistentState(IConfiguration configuration)
: this(configuration[LogLocation])

Check warning on line 26 in src/SlimData/SlimPersistentState.cs

View workflow job for this annotation

GitHub Actions / SonarCloud

Possible null reference argument for parameter 'path' in 'SlimPersistentState.SlimPersistentState(string path)'.

Check warning on line 26 in src/SlimData/SlimPersistentState.cs

View workflow job for this annotation

GitHub Actions / SonarCloud

Possible null reference argument for parameter 'path' in 'SlimPersistentState.SlimPersistentState(string path)'.
{
}

Expand Down
2 changes: 2 additions & 0 deletions src/SlimFaas/HistorySynchronizationWorker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
long ticksMemory = historyHttpMemoryService.GetTicksLastCall(function.Deployment);
if (ticksInDatabase > ticksMemory)
{
logger.LogInformation("HistorySynchronizationWorker: Synchronizing history for {Function} to {Ticks} from Database", function.Deployment, ticksInDatabase);
historyHttpMemoryService.SetTickLastCall(function.Deployment, ticksInDatabase);
}
else if (ticksInDatabase < ticksMemory)
{
logger.LogInformation("HistorySynchronizationWorker: Synchronizing history for {Function} to {Ticks} from Memory", function.Deployment, ticksMemory);
await historyHttpDatabaseService.SetTickLastCallAsync(function.Deployment, ticksMemory);
}
}
Expand Down
12 changes: 9 additions & 3 deletions src/SlimFaas/Kubernetes/KubernetesService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ public record DeploymentInformation(string Deployment, string Namespace, IList<P
IList<string>? SubscribeEvents = null,
FunctionVisibility Visibility = FunctionVisibility.Public,
IList<string>? PathsStartWithVisibility = null,
IList<string>? ExcludeDeploymentsFromVisibilityPrivate = null
IList<string>? ExcludeDeploymentsFromVisibilityPrivate = null,
string ResourceVersion = ""
);

public record PodInformation(string Name, bool? Started, bool? Ready, string Ip, string DeploymentName);
Expand Down Expand Up @@ -249,7 +250,8 @@ private static void AddDeployments(string kubeNamespace, V1DeploymentList deploy
annotations.TryGetValue(PathsStartWithVisibility, out string? valueUrlsStartWithVisibility)
? valueUrlsStartWithVisibility.Split(',').ToList()
: new List<string>(),
annotations.TryGetValue(ExcludeDeploymentsFromVisibilityPrivate, out string? valueExcludeDeploymentsFromVisibilityPrivate) ? valueExcludeDeploymentsFromVisibilityPrivate.Split(',').ToList() : new List<string>()
annotations.TryGetValue(ExcludeDeploymentsFromVisibilityPrivate, out string? valueExcludeDeploymentsFromVisibilityPrivate) ? valueExcludeDeploymentsFromVisibilityPrivate.Split(',').ToList() : new List<string>(),
deploymentListItem.Metadata.ResourceVersion
);
deploymentInformationList.Add(deploymentInformation);
}
Expand Down Expand Up @@ -323,7 +325,11 @@ private static void AddStatefulSets(string kubeNamespace, V1StatefulSetList depl
annotations.TryGetValue(DefaultVisibility, out string? visibility)
? Enum.Parse<FunctionVisibility>(visibility)
: FunctionVisibility.Public,
annotations.TryGetValue(ExcludeDeploymentsFromVisibilityPrivate, out string? valueExcludeDeploymentsFromVisibilityPrivate) ? valueExcludeDeploymentsFromVisibilityPrivate.Split(',').ToList() : new List<string>());
annotations.TryGetValue(PathsStartWithVisibility, out string? valueUrlsStartWithVisibility)
? valueUrlsStartWithVisibility.Split(',').ToList()
: new List<string>(),
annotations.TryGetValue(ExcludeDeploymentsFromVisibilityPrivate, out string? valueExcludeDeploymentsFromVisibilityPrivate) ? valueExcludeDeploymentsFromVisibilityPrivate.Split(',').ToList() : new List<string>(),
deploymentListItem.Metadata.ResourceVersion);

deploymentInformationList.Add(deploymentInformation);
}
Expand Down
34 changes: 32 additions & 2 deletions src/SlimFaas/ReplicasService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,35 @@ public async Task<DeploymentsInformations> SyncDeploymentsAsync(string kubeNames
DeploymentsInformations deployments = await kubernetesService.ListFunctionsAsync(kubeNamespace);
lock (Lock)
{
if (logger.IsEnabled(LogLevel.Information))
{
foreach (DeploymentInformation deploymentInformation in deployments.Functions)
{
var currentDeployment = _deployments.Functions.FirstOrDefault(f =>
f.Deployment == deploymentInformation.Deployment &&
f.ResourceVersion == deploymentInformation.ResourceVersion);
if (currentDeployment == null)
{
// Un log information avec toutes les informations de toutes les propriété de la fonction
logger.LogInformation("New deployment {Deployment} \n" +
"with {Replicas} replicas \n" +
"with {ReplicasAtStart} replicas at start \n" +
"with {ReplicasMin} replicas min \n" +
"with {ReplicasStartAsSoonAsOneFunctionRetrieveARequest} replicas start as soon as one function retrieve a request \n" +
"with {TimeoutSecondBeforeSetReplicasMin} timeout second before set replicas min \n" +
"with {PodType} pod type \n" +
"with {ResourceVersion} resource version \n"+
"with {NumberParallelRequest} number parallel request \n",
deploymentInformation.Deployment, deploymentInformation.Replicas, deploymentInformation.ReplicasAtStart, deploymentInformation.ReplicasMin,
deploymentInformation.ReplicasStartAsSoonAsOneFunctionRetrieveARequest, deploymentInformation.TimeoutSecondBeforeSetReplicasMin,
deploymentInformation.PodType, deploymentInformation.ResourceVersion, deploymentInformation.NumberParallelRequest);

}
}

}


_deployments = deployments;
}
return deployments;
Expand Down Expand Up @@ -101,14 +130,14 @@ public async Task CheckScaleAsync(string kubeNamespace)
TimeSpan.FromSeconds(GetTimeoutSecondBeforeSetReplicasMin(deploymentInformation, DateTime.UtcNow)) <
TimeSpan.FromTicks(DateTime.UtcNow.Ticks);
int currentScale = deploymentInformation.Replicas;

if (timeElapsedWithoutRequest)
{
if (currentScale <= deploymentInformation.ReplicasMin)
{
continue;
}

logger.LogInformation("Scale down {Deployment} from {currentScale} to {ReplicasMin}", deploymentInformation.Deployment, currentScale, deploymentInformation.ReplicasMin);
Task<ReplicaRequest?> task = kubernetesService.ScaleAsync(new ReplicaRequest(
Replicas: deploymentInformation.ReplicasMin,
Deployment: deploymentInformation.Deployment,
Expand All @@ -118,8 +147,9 @@ public async Task CheckScaleAsync(string kubeNamespace)

tasks.Add(task);
}
else if (currentScale is 0 && DependsOnReady(deploymentInformation))
else if ((currentScale is 0 || currentScale < deploymentInformation.ReplicasMin) && DependsOnReady(deploymentInformation))
{
logger.LogInformation("Scale up {Deployment} from {currentScale} to {Replica at start}", deploymentInformation.Deployment, currentScale, deploymentInformation.ReplicasAtStart);
Task<ReplicaRequest?> task = kubernetesService.ScaleAsync(new ReplicaRequest(
Replicas: deploymentInformation.ReplicasAtStart,
Deployment: deploymentInformation.Deployment,
Expand Down
15 changes: 11 additions & 4 deletions src/SlimFaas/SlimProxyMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -299,22 +299,29 @@ private async Task BuildPublishResponseAsync(HttpContext context, HistoryHttpMem
var slimFaasSubscribeEvents = _slimFaasSubscribeEvents.Where(s => s.Key == eventName);
if (functions.Count <= 0 && !slimFaasSubscribeEvents.Any())
{
logger.LogDebug("Return 404 from event: {EventName}", eventName);
logger.LogDebug("Publish-event {EventName} : Return 404 from event", eventName);
context.Response.StatusCode = 404;
return;
}
var lastSetTicks = DateTime.UtcNow.Ticks;

List<DeploymentInformation> calledFunctions = new();

List<Task<HttpResponseMessage>> tasks = new();
foreach (DeploymentInformation function in functions)
{
foreach (var pod in function.Pods)
{
logger.LogDebug("Pod {PodName} is ready: {PodReady}", pod.Name, pod.Ready);
if (pod.Ready != true)
if (pod.Ready is not true)
{
continue;
}

if (!calledFunctions.Contains(function))
{
calledFunctions.Add(function);
}
logger.LogInformation("Publish-event {EventName} : Deployment {Deployment} Pod {PodName} is ready: {PodReady}", eventName, function.Deployment, pod.Name, pod.Ready);
historyHttpService.SetTickLastCall(function.Deployment, lastSetTicks);

string baseFunctionPodUrl =
Expand Down Expand Up @@ -350,7 +357,7 @@ private async Task BuildPublishResponseAsync(HttpContext context, HistoryHttpMem
}

lastSetTicks = DateTime.UtcNow.Ticks;
foreach (DeploymentInformation function in functions)
foreach (DeploymentInformation function in calledFunctions)
{
historyHttpService.SetTickLastCall(function.Deployment, lastSetTicks);
}
Expand Down
2 changes: 1 addition & 1 deletion src/SlimFaas/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"Microsoft.AspNetCore": "Error",
"DotNext.Net.Cluster": "Error",
"SlimData": "Error",
"SlimFaas": "Error"
"SlimFaas": "Information"
}
},
"UseKubeConfig": false,
Expand Down
2 changes: 1 addition & 1 deletion tests/SlimData.Tests/SlimData.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<PackageReference Include="Microsoft.CodeCoverage" Version="17.10.0" />
<FrameworkReference Include="Microsoft.AspNetCore.App" PrivateAssets="all"/>
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
<PackageReference Include="DotNext.AspNetCore.Cluster" Version="5.6.0" />
<PackageReference Include="DotNext.AspNetCore.Cluster" Version="5.7.0" />
<PackageReference Include="xunit" Version="2.8.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
Loading